mirror of
https://github.com/jcreek/LivingDexTracker.git
synced 2026-07-16 04:23:43 +00:00
Compare commits
92 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a209ab3b63 | |||
| 10221812a8 | |||
| 33fbf6e3ac | |||
| 1531fbe591 | |||
| c8a82c0bbe | |||
| 8a9185944d | |||
| 9d4ed604a8 | |||
| c97347722a | |||
| 3a195f6176 | |||
| fed7003972 | |||
| 4be21fb66b | |||
| bb3b646587 | |||
| 2fb2b2c06d | |||
| 4dc5d86a74 | |||
| a61b6a3f50 | |||
| f5c580b828 | |||
| 2db9045d3d | |||
| 1a6232f5bd | |||
| f2da6e5b37 | |||
| e871fa7fea | |||
| dbafe342b7 | |||
| e371e4b813 | |||
| 1cdbab0f6c | |||
| c72adff5bf | |||
| 171a202ef6 | |||
| 2608f3dba6 | |||
| e9c483045a | |||
| 955a8c869e | |||
| 5fdc43124e | |||
| 3d42bef3e5 | |||
| 72254fb479 | |||
| a3cfb4e83c | |||
| 2a33dc1781 | |||
| 2404499858 | |||
| 8c5bc48802 | |||
| f5ae56f6a6 | |||
| 8a7e2ea631 | |||
| 228a37a2f6 | |||
| f420b6372e | |||
| f6741f4b1e | |||
| a375489cc6 | |||
| 092ffde8e4 | |||
| 469290662f | |||
| ba06fbee2b | |||
| 76b617b349 | |||
| 8262dbfcf4 | |||
| c666583058 | |||
| 61feede30a | |||
| 9e21f8edbf | |||
| 7dda58ec24 | |||
| f64f8b2bc6 | |||
| 062eff0433 | |||
| e4e133b333 | |||
| 0fe76a9ec6 | |||
| d41b467d43 | |||
| 6712339640 | |||
| 7c0dec0cb4 | |||
| 4c9631e00f | |||
| c6db2a9add | |||
| 4952eda3e0 | |||
| fa3fe31fb6 | |||
| 70c31f6798 | |||
| 999cb8bf3f | |||
| ae4c27ae6e | |||
| 4d4aecf2f6 | |||
| a7838b8e7b | |||
| d581e26234 | |||
| 9c22786dd5 | |||
| 69c80a5e39 | |||
| bc4e69e95e | |||
| 89993f305a | |||
| e78a562725 | |||
| 4c71e92780 | |||
| 60bc76705b | |||
| ab225b661f | |||
| 21f8d35bb7 | |||
| df66370e02 | |||
| 364b593f08 | |||
| eacd695a40 | |||
| 97be847b44 | |||
| 2b220f1437 | |||
| 99655d3864 | |||
| 869be67c54 | |||
| 6cfa2bd6d7 | |||
| b7996e50a6 | |||
| 88b5edb4b9 | |||
| 596bfa3ec1 | |||
| aee56d0fc9 | |||
| 3c1ae70392 | |||
| 5650a6d8d7 | |||
| 2de4e8b54b | |||
| b2b0cf0035 |
+3
-9
@@ -1,9 +1,3 @@
|
|||||||
PUBLIC_SUPABASE_URL="your-supabase-project-url"
|
MONGO_URL=""
|
||||||
PUBLIC_SUPABASE_ANON_KEY="your-supabase-anon-key"
|
PUBLIC_SUPABASE_URL=""
|
||||||
SUPABASE_SERVICE_ROLE_KEY="your-supabase-service-role-key"
|
PUBLIC_SUPABASE_ANON_KEY=""
|
||||||
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER="false"
|
|
||||||
|
|
||||||
GOOGLE_OAUTH_CLIENT_ID="your-google-client-id"
|
|
||||||
GOOGLE_OAUTH_CLIENT_SECRET="your-google-client-secret"
|
|
||||||
DROPBOX_OAUTH_CLIENT_ID="your-dropbox-client-id"
|
|
||||||
DROPBOX_OAUTH_CLIENT_SECRET="your-dropbox-client-secret"
|
|
||||||
@@ -4,24 +4,18 @@ A web app to track completion of a living Pokédex.
|
|||||||
|
|
||||||
## Developing
|
## Developing
|
||||||
|
|
||||||
1. Clone the repository
|
Cloned the repository you can install the dependencies with `npm install`, and start a development server:
|
||||||
2. Install the dependencies with `npm install`
|
|
||||||
3. Ensure that Docker is running
|
|
||||||
4. An example `.env` file is provided in the repository. You will need to copy `.env.example` to `.env` and fill in the values with your own credentials. For local development with Supabase running in Docker, you can use the following values:
|
|
||||||
|
|
||||||
- The `PUBLIC_SUPABASE_URL` will be `"http://127.0.0.1:54321"`
|
```bash
|
||||||
- The `PUBLIC_SUPABASE_ANON_KEY` will be the 'Publishable' authentication key displayed when you run Supabase in the terminal
|
npm run dev
|
||||||
- The `SUPABASE_SERVICE_ROLE_KEY` will be the 'Secret' authentication key displayed when you run Supabase in the terminal
|
|
||||||
|
|
||||||
5. Start local Supabase and a development server with `npm run dev:supabase`
|
# or start the server and open the app in a new browser tab
|
||||||
6. The Pokédex data is automatically seeded via database migrations when Supabase starts
|
npm run dev -- --open
|
||||||
7. Create an account using the sign-up form and access the email it sends in [MailPit](http://127.0.0.1:54324/) to verify your email address.
|
```
|
||||||
N.B. All local emails are captured by MailPit when running Supabase in Docker.
|
|
||||||
8. You can now use [the app](http://localhost:5173/).
|
|
||||||
|
|
||||||
## Reference Data Updates
|
An example `.env` file is provided in the repository. You will need to copy `.env.example` to `.env` and fill in the values with your own credentials.
|
||||||
|
|
||||||
The seed data lives in `supabase/migrations/20260118001000_seed_reference_data.sql`. Update that migration directly when new data is added. You can access a local copy of [Supabase](http://localhost:54323/) to check it.
|
Once you have done this, you can seed the Pokédex data using the /api/seed endpoint. You will need to comment out the `return;` at the beginning of the `GET` function in `/src/routes/api/seed.ts` to do this. Make sure you remember to uncomment it afterwards.
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
@@ -33,28 +27,14 @@ npm run build
|
|||||||
|
|
||||||
You can preview the production build with `npm run preview`.
|
You can preview the production build with `npm run preview`.
|
||||||
|
|
||||||
## Sprites
|
|
||||||
|
|
||||||
The app uses WebP sprites from `static/sprites-small`. During builds we generate this folder from the
|
|
||||||
full-resolution PNGs in `static/sprites`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
npm run sprites:build
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to serve sprites locally, set `PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER="true"` in `.env`.
|
|
||||||
Otherwise the app defaults to GitHub raw for `static/sprites-small`.
|
|
||||||
|
|
||||||
## Hosting
|
## Hosting
|
||||||
|
|
||||||
The app is hosted on [Netlify](https://www.netlify.com/) at [pokedex.jcreek.co.uk](https://pokedex.jcreek.co.uk/).
|
The app is hosted on [Netlify](https://www.netlify.com/) at [pokedex.jcreek.co.uk](https://pokedex.jcreek.co.uk/).
|
||||||
|
|
||||||
The Pokédex data is stored in a [Supabase](https://supabase.com/) database.
|
The Pokédex data is stored in a [MongoDB](https://www.mongodb.com/) database hosted on [MongoDB Cloud](https://cloud.mongodb.com/).
|
||||||
|
|
||||||
User authentication is handled by [Supabase Auth](https://supabase.com/auth).
|
User authentication is handled by [Supabase Auth](https://supabase.com/auth).
|
||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
The living dex tracker's sprite collection is derived from [PokéAPI Sprites](https://github.com/PokeAPI/sprites)
|
The living dex tracker's sprite collection is taken from [PokéAPI Sprites](https://github.com/PokeAPI/sprites), which is licensed under [the Creative Commons CC0 1.0 Universal license](https://github.com/PokeAPI/sprites/blob/master/LICENCE.txt).
|
||||||
and converted to smaller WebP files in `static/sprites-small`. PokéAPI sprites are licensed under
|
|
||||||
[the Creative Commons CC0 1.0 Universal license](https://github.com/PokeAPI/sprites/blob/master/LICENCE.txt).
|
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
dexId,gameDisplayName,dexDisplayName,sortOrder,isDlc,parentDexId,file
|
|
||||||
red-kanto,Red,Kanto,1,false,,native-game-dexes/red-blue-yellow.csv
|
|
||||||
blue-kanto,Blue,Kanto,1,false,,native-game-dexes/red-blue-yellow.csv
|
|
||||||
yellow-kanto,Yellow,Kanto,1,false,,native-game-dexes/red-blue-yellow.csv
|
|
||||||
gold-johto,Gold,Johto,1,false,,native-game-dexes/gold-silver-crystal.csv
|
|
||||||
silver-johto,Silver,Johto,1,false,,native-game-dexes/gold-silver-crystal.csv
|
|
||||||
crystal-johto,Crystal,Johto,1,false,,native-game-dexes/gold-silver-crystal.csv
|
|
||||||
ruby-hoenn,Ruby,Hoenn,1,false,,native-game-dexes/ruby-sapphire-emerald.csv
|
|
||||||
sapphire-hoenn,Sapphire,Hoenn,1,false,,native-game-dexes/ruby-sapphire-emerald.csv
|
|
||||||
emerald-hoenn,Emerald,Hoenn,1,false,,native-game-dexes/ruby-sapphire-emerald.csv
|
|
||||||
firered-kanto,FireRed,Kanto,1,false,,native-game-dexes/fire-red-leaf-green.csv
|
|
||||||
leafgreen-kanto,LeafGreen,Kanto,1,false,,native-game-dexes/fire-red-leaf-green.csv
|
|
||||||
diamond-sinnoh,Diamond,Sinnoh,1,false,,native-game-dexes/diamond-pearl.csv
|
|
||||||
pearl-sinnoh,Pearl,Sinnoh,1,false,,native-game-dexes/diamond-pearl.csv
|
|
||||||
platinum-sinnoh,Platinum,Sinnoh,1,false,,native-game-dexes/platinum.csv
|
|
||||||
heart-gold-johto,Heart Gold,Johto,1,false,,native-game-dexes/heart-gold-soul-silver.csv
|
|
||||||
soul-silver-johto,Soul Silver,Johto,1,false,,native-game-dexes/heart-gold-soul-silver.csv
|
|
||||||
black-unova,Black,Unova,1,false,,native-game-dexes/black-white.csv
|
|
||||||
white-unova,White,Unova,1,false,,native-game-dexes/black-white.csv
|
|
||||||
black-2-unova,Black 2,Unova,1,false,,native-game-dexes/black-2-white-2.csv
|
|
||||||
white-2-unova,White 2,Unova,1,false,,native-game-dexes/black-2-white-2.csv
|
|
||||||
x-central-kalos,X,Central Kalos,1,false,,native-game-dexes/x-y-central-kalos.csv
|
|
||||||
x-coastal-kalos,X,Coastal Kalos,2,false,,native-game-dexes/x-y-coastal-kalos.csv
|
|
||||||
x-mountain-kalos,X,Mountain Kalos,3,false,,native-game-dexes/x-y-mountain-kalos.csv
|
|
||||||
y-central-kalos,Y,Central Kalos,1,false,,native-game-dexes/x-y-central-kalos.csv
|
|
||||||
y-coastal-kalos,Y,Coastal Kalos,2,false,,native-game-dexes/x-y-coastal-kalos.csv
|
|
||||||
y-mountain-kalos,Y,Mountain Kalos,3,false,,native-game-dexes/x-y-mountain-kalos.csv
|
|
||||||
omega-ruby-hoenn,Omega Ruby,Hoenn,1,false,,native-game-dexes/omega-ruby-alpha-sapphire.csv
|
|
||||||
alpha-sapphire-hoenn,Alpha Sapphire,Hoenn,1,false,,native-game-dexes/omega-ruby-alpha-sapphire.csv
|
|
||||||
sun-alola,Sun,Alola,1,false,,native-game-dexes/sun-moon-alola.csv
|
|
||||||
moon-alola,Moon,Alola,1,false,,native-game-dexes/sun-moon-alola.csv
|
|
||||||
ultra-sun-alola,Ultra Sun,Alola,1,false,,native-game-dexes/ultra-sun-ultra-moon-alola.csv
|
|
||||||
ultra-moon-alola,Ultra Moon,Alola,1,false,,native-game-dexes/ultra-sun-ultra-moon-alola.csv
|
|
||||||
lg-pikachu-kanto,LG: Pikachu,Kanto,1,false,,native-game-dexes/lets-go-pikachu-eevee.csv
|
|
||||||
lg-eevee-kanto,LG: Eevee,Kanto,1,false,,native-game-dexes/lets-go-pikachu-eevee.csv
|
|
||||||
sword-galar,Sword,Galar,1,false,,native-game-dexes/sword-shield.csv
|
|
||||||
sword-isle-armor,Sword,Isle of Armor,2,true,sword-galar,native-game-dexes/sword-shield-isle-armor.csv
|
|
||||||
sword-crown-tundra,Sword,Crown Tundra,3,true,sword-galar,native-game-dexes/sword-shield-crown-tundra.csv
|
|
||||||
shield-galar,Shield,Galar,1,false,,native-game-dexes/sword-shield.csv
|
|
||||||
shield-isle-armor,Shield,Isle of Armor,2,true,shield-galar,native-game-dexes/sword-shield-isle-armor.csv
|
|
||||||
shield-crown-tundra,Shield,Crown Tundra,3,true,shield-galar,native-game-dexes/sword-shield-crown-tundra.csv
|
|
||||||
brilliant-diamond-sinnoh,Brilliant Diamond,Sinnoh,1,false,,native-game-dexes/brilliant-diamond-shining-pearl.csv
|
|
||||||
shining-pearl-sinnoh,Shining Pearl,Sinnoh,1,false,,native-game-dexes/brilliant-diamond-shining-pearl.csv
|
|
||||||
legends-arceus-hisui,Legends: Arceus,Hisui,1,false,,native-game-dexes/legends-arceus.csv
|
|
||||||
scarlet-paldea,Scarlet,Paldea,1,false,,native-game-dexes/scarlet-violet.csv
|
|
||||||
scarlet-kitakami,Scarlet,Kitakami,2,true,scarlet-paldea,native-game-dexes/scarlet-violet-kitakami.csv
|
|
||||||
scarlet-blueberry,Scarlet,Blueberry,3,true,scarlet-paldea,native-game-dexes/scarlet-violet-blueberry.csv
|
|
||||||
violet-paldea,Violet,Paldea,1,false,,native-game-dexes/scarlet-violet.csv
|
|
||||||
violet-kitakami,Violet,Kitakami,2,true,violet-paldea,native-game-dexes/scarlet-violet-kitakami.csv
|
|
||||||
violet-blueberry,Violet,Blueberry,3,true,violet-paldea,native-game-dexes/scarlet-violet-blueberry.csv
|
|
||||||
legends-z-a-kalos,Legends: Z-A,Kalos,1,false,,native-game-dexes/legends-z-a.csv
|
|
||||||
legends-z-a-mega-dimension,Legends: Z-A,Mega Dimension,2,true,legends-z-a-kalos,native-game-dexes/legends-z-a-mega-dimension.csv
|
|
||||||
|
@@ -1,46 +0,0 @@
|
|||||||
game,region,releaseYear
|
|
||||||
Red,Kanto,1996
|
|
||||||
Blue,Kanto,1996
|
|
||||||
Yellow,Kanto,1998
|
|
||||||
Gold,Johto,1999
|
|
||||||
Silver,Johto,1999
|
|
||||||
Crystal,Johto,2000
|
|
||||||
Ruby,Hoenn,2002
|
|
||||||
Sapphire,Hoenn,2002
|
|
||||||
Colosseum,Orre,2003
|
|
||||||
Emerald,Hoenn,2004
|
|
||||||
FireRed,Kanto,2004
|
|
||||||
LeafGreen,Kanto,2004
|
|
||||||
XD: Gale of Darkness,Orre,2005
|
|
||||||
Diamond,Sinnoh,2006
|
|
||||||
Pearl,Sinnoh,2006
|
|
||||||
Platinum,Sinnoh,2008
|
|
||||||
Ranch,Ranch,2008
|
|
||||||
Heart Gold,Johto,2009
|
|
||||||
Soul Silver,Johto,2009
|
|
||||||
Black,Unova,2010
|
|
||||||
White,Unova,2010
|
|
||||||
Black 2,Unova,2012
|
|
||||||
White 2,Unova,2012
|
|
||||||
Dream Radar,Unova,2012
|
|
||||||
X,Kalos,2013
|
|
||||||
Y,Kalos,2013
|
|
||||||
Omega Ruby,Hoenn,2014
|
|
||||||
Alpha Sapphire,Hoenn,2014
|
|
||||||
Sun,Alola,2016
|
|
||||||
Moon,Alola,2016
|
|
||||||
Moon (demo),Alola,2016
|
|
||||||
Go,Go,2016
|
|
||||||
Ultra Sun,Alola,2017
|
|
||||||
Ultra Moon,Alola,2017
|
|
||||||
LG: Pikachu,Kanto,2018
|
|
||||||
LG: Eevee,Kanto,2018
|
|
||||||
Sword,Galar,2019
|
|
||||||
Shield,Galar,2019
|
|
||||||
Home,Home,2020
|
|
||||||
Brilliant Diamond,Sinnoh,2021
|
|
||||||
Shining Pearl,Sinnoh,2021
|
|
||||||
Legends: Arceus,Hisui,2022
|
|
||||||
Scarlet,Paldea,2022
|
|
||||||
Violet,Paldea,2022
|
|
||||||
Legends: Z-A,Kalos,2025
|
|
||||||
|
@@ -1,302 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
0,Victini,,
|
|
||||||
1,Snivy,,
|
|
||||||
2,Servine,,
|
|
||||||
3,Serperior,,
|
|
||||||
4,Tepig,,
|
|
||||||
5,Pignite,,
|
|
||||||
6,Emboar,,
|
|
||||||
7,Oshawott,,
|
|
||||||
8,Dewott,,
|
|
||||||
9,Samurott,,
|
|
||||||
10,Patrat,,
|
|
||||||
11,Watchog,,
|
|
||||||
12,Purrloin,,
|
|
||||||
13,Liepard,,
|
|
||||||
14,Pidove,,
|
|
||||||
15,Tranquill,,
|
|
||||||
16,Unfezant,,
|
|
||||||
17,Sewaddle,,
|
|
||||||
18,Swadloon,,
|
|
||||||
19,Leavanny,,
|
|
||||||
20,Sunkern,,
|
|
||||||
21,Sunflora,,
|
|
||||||
22,Lillipup,,
|
|
||||||
23,Herdier,,
|
|
||||||
24,Stoutland,,
|
|
||||||
25,Mareep,,
|
|
||||||
26,Flaaffy,,
|
|
||||||
27,Ampharos,,
|
|
||||||
28,Psyduck,,
|
|
||||||
29,Golduck,,
|
|
||||||
30,Azurill,,
|
|
||||||
31,Marill,,
|
|
||||||
32,Azumarill,,
|
|
||||||
33,Riolu,,
|
|
||||||
34,Lucario,,
|
|
||||||
35,Dunsparce,,
|
|
||||||
36,Audino,,
|
|
||||||
37,Pansage,,
|
|
||||||
38,Simisage,,
|
|
||||||
39,Pansear,,
|
|
||||||
40,Simisear,,
|
|
||||||
41,Panpour,,
|
|
||||||
42,Simipour,,
|
|
||||||
43,Venipede,,
|
|
||||||
44,Whirlipede,,
|
|
||||||
45,Scolipede,,
|
|
||||||
46,Koffing,,
|
|
||||||
47,Weezing,,
|
|
||||||
48,Magnemite,,
|
|
||||||
49,Magneton,,
|
|
||||||
50,Magnezone,,
|
|
||||||
51,Growlithe,,
|
|
||||||
52,Arcanine,,
|
|
||||||
53,Magby,,
|
|
||||||
54,Magmar,,
|
|
||||||
55,Magmortar,,
|
|
||||||
56,Elekid,,
|
|
||||||
57,Electabuzz,,
|
|
||||||
58,Electivire,,
|
|
||||||
59,Rattata,,
|
|
||||||
60,Raticate,,
|
|
||||||
61,Zubat,,
|
|
||||||
62,Golbat,,
|
|
||||||
63,Crobat,,
|
|
||||||
64,Grimer,,
|
|
||||||
65,Muk,,
|
|
||||||
66,Woobat,,
|
|
||||||
67,Swoobat,,
|
|
||||||
68,Roggenrola,,
|
|
||||||
69,Boldore,,
|
|
||||||
70,Gigalith,,
|
|
||||||
71,Onix,,
|
|
||||||
72,Steelix,,
|
|
||||||
73,Timburr,,
|
|
||||||
74,Gurdurr,,
|
|
||||||
75,Conkeldurr,,
|
|
||||||
76,Drilbur,,
|
|
||||||
77,Excadrill,,
|
|
||||||
78,Skitty,,
|
|
||||||
79,Delcatty,,
|
|
||||||
80,Buneary,,
|
|
||||||
81,Lopunny,,
|
|
||||||
82,Cottonee,,
|
|
||||||
83,Whimsicott,,
|
|
||||||
84,Petilil,,
|
|
||||||
85,Lilligant,,
|
|
||||||
86,Munna,,
|
|
||||||
87,Musharna,,
|
|
||||||
88,Cleffa,,
|
|
||||||
89,Clefairy,,
|
|
||||||
90,Clefable,,
|
|
||||||
91,Eevee,,
|
|
||||||
92,Vaporeon,,
|
|
||||||
93,Jolteon,,
|
|
||||||
94,Flareon,,
|
|
||||||
95,Espeon,,
|
|
||||||
96,Umbreon,,
|
|
||||||
97,Leafeon,,
|
|
||||||
98,Glaceon,,
|
|
||||||
99,Sandile,,
|
|
||||||
100,Krokorok,,
|
|
||||||
101,Krookodile,,
|
|
||||||
102,Darumaka,,
|
|
||||||
103,Darmanitan,,
|
|
||||||
104,Basculin,,
|
|
||||||
105,Trubbish,,
|
|
||||||
106,Garbodor,,
|
|
||||||
107,Minccino,,
|
|
||||||
108,Cinccino,,
|
|
||||||
109,Rufflet,,
|
|
||||||
110,Braviary,,
|
|
||||||
111,Vullaby,,
|
|
||||||
112,Mandibuzz,,
|
|
||||||
113,Sandshrew,,
|
|
||||||
114,Sandslash,,
|
|
||||||
115,Dwebble,,
|
|
||||||
116,Crustle,,
|
|
||||||
117,Scraggy,,
|
|
||||||
118,Scrafty,,
|
|
||||||
119,Maractus,,
|
|
||||||
120,Sigilyph,,
|
|
||||||
121,Trapinch,,
|
|
||||||
122,Vibrava,,
|
|
||||||
123,Flygon,,
|
|
||||||
124,Yamask,,
|
|
||||||
125,Cofagrigus,,
|
|
||||||
126,Tirtouga,,
|
|
||||||
127,Carracosta,,
|
|
||||||
128,Archen,,
|
|
||||||
129,Archeops,,
|
|
||||||
130,Klink,,
|
|
||||||
131,Klang,,
|
|
||||||
132,Klinklang,,
|
|
||||||
133,Budew,,
|
|
||||||
134,Roselia,,
|
|
||||||
135,Roserade,,
|
|
||||||
136,Gothita,,
|
|
||||||
137,Gothorita,,
|
|
||||||
138,Gothitelle,,
|
|
||||||
139,Solosis,,
|
|
||||||
140,Duosion,,
|
|
||||||
141,Reuniclus,,
|
|
||||||
142,Combee,,
|
|
||||||
143,Vespiquen,,
|
|
||||||
144,Emolga,,
|
|
||||||
145,Heracross,,
|
|
||||||
146,Pinsir,,
|
|
||||||
147,Blitzle,,
|
|
||||||
148,Zebstrika,,
|
|
||||||
149,Buizel,,
|
|
||||||
150,Floatzel,,
|
|
||||||
151,Zorua,,
|
|
||||||
152,Zoroark,,
|
|
||||||
153,Ducklett,,
|
|
||||||
154,Swanna,,
|
|
||||||
155,Karrablast,,
|
|
||||||
156,Escavalier,,
|
|
||||||
157,Shelmet,,
|
|
||||||
158,Accelgor,,
|
|
||||||
159,Deerling,,
|
|
||||||
160,Sawsbuck,,
|
|
||||||
161,Foongus,,
|
|
||||||
162,Amoonguss,,
|
|
||||||
163,Castform,,
|
|
||||||
164,Nosepass,,
|
|
||||||
165,Probopass,,
|
|
||||||
166,Aron,,
|
|
||||||
167,Lairon,,
|
|
||||||
168,Aggron,,
|
|
||||||
169,Baltoy,,
|
|
||||||
170,Claydol,,
|
|
||||||
171,Larvesta,,
|
|
||||||
172,Volcarona,,
|
|
||||||
173,Joltik,,
|
|
||||||
174,Galvantula,,
|
|
||||||
175,Ferroseed,,
|
|
||||||
176,Ferrothorn,,
|
|
||||||
177,Tynamo,,
|
|
||||||
178,Eelektrik,,
|
|
||||||
179,Eelektross,,
|
|
||||||
180,Frillish,,
|
|
||||||
181,Jellicent,,
|
|
||||||
182,Alomomola,,
|
|
||||||
183,Axew,,
|
|
||||||
184,Fraxure,,
|
|
||||||
185,Haxorus,,
|
|
||||||
186,Zangoose,,
|
|
||||||
187,Seviper,,
|
|
||||||
188,Elgyem,,
|
|
||||||
189,Beheeyem,,
|
|
||||||
190,Litwick,,
|
|
||||||
191,Lampent,,
|
|
||||||
192,Chandelure,,
|
|
||||||
193,Heatmor,,
|
|
||||||
194,Durant,,
|
|
||||||
195,Cubchoo,,
|
|
||||||
196,Beartic,,
|
|
||||||
197,Cryogonal,,
|
|
||||||
198,Tornadus,,
|
|
||||||
199,Thundurus,,
|
|
||||||
200,Landorus,,
|
|
||||||
201,Skorupi,,
|
|
||||||
202,Drapion,,
|
|
||||||
203,Skarmory,,
|
|
||||||
204,Numel,,
|
|
||||||
205,Camerupt,,
|
|
||||||
206,Spoink,,
|
|
||||||
207,Grumpig,,
|
|
||||||
208,Drifloon,,
|
|
||||||
209,Drifblim,,
|
|
||||||
210,Shuppet,,
|
|
||||||
211,Banette,,
|
|
||||||
212,Wingull,,
|
|
||||||
213,Pelipper,,
|
|
||||||
214,Lunatone,,
|
|
||||||
215,Solrock,,
|
|
||||||
216,Absol,,
|
|
||||||
217,Tangela,,
|
|
||||||
218,Tangrowth,,
|
|
||||||
219,Mienfoo,,
|
|
||||||
220,Mienshao,,
|
|
||||||
221,Gligar,,
|
|
||||||
222,Gliscor,,
|
|
||||||
223,Pawniard,,
|
|
||||||
224,Bisharp,,
|
|
||||||
225,Cobalion,,
|
|
||||||
226,Terrakion,,
|
|
||||||
227,Virizion,,
|
|
||||||
228,Tympole,,
|
|
||||||
229,Palpitoad,,
|
|
||||||
230,Seismitoad,,
|
|
||||||
231,Stunfisk,,
|
|
||||||
232,Shuckle,,
|
|
||||||
233,Mantyke,,
|
|
||||||
234,Mantine,,
|
|
||||||
235,Remoraid,,
|
|
||||||
236,Octillery,,
|
|
||||||
237,Corsola,,
|
|
||||||
238,Staryu,,
|
|
||||||
239,Starmie,,
|
|
||||||
240,Wailmer,,
|
|
||||||
241,Wailord,,
|
|
||||||
242,Lapras,,
|
|
||||||
243,Spheal,,
|
|
||||||
244,Sealeo,,
|
|
||||||
245,Walrein,,
|
|
||||||
246,Swablu,,
|
|
||||||
247,Altaria,,
|
|
||||||
248,Vulpix,,
|
|
||||||
249,Ninetales,,
|
|
||||||
250,Bronzor,,
|
|
||||||
251,Bronzong,,
|
|
||||||
252,Sneasel,,
|
|
||||||
253,Weavile,,
|
|
||||||
254,Delibird,,
|
|
||||||
255,Vanillite,,
|
|
||||||
256,Vanillish,,
|
|
||||||
257,Vanilluxe,,
|
|
||||||
258,Swinub,,
|
|
||||||
259,Piloswine,,
|
|
||||||
260,Mamoswine,,
|
|
||||||
261,Ditto,,
|
|
||||||
262,Beldum,,
|
|
||||||
263,Metang,,
|
|
||||||
264,Metagross,,
|
|
||||||
265,Seel,,
|
|
||||||
266,Dewgong,,
|
|
||||||
267,Throh,,
|
|
||||||
268,Sawk,,
|
|
||||||
269,Bouffalant,,
|
|
||||||
270,Druddigon,,
|
|
||||||
271,Golett,,
|
|
||||||
272,Golurk,,
|
|
||||||
273,Deino,,
|
|
||||||
274,Zweilous,,
|
|
||||||
275,Hydreigon,,
|
|
||||||
276,Slakoth,,
|
|
||||||
277,Vigoroth,,
|
|
||||||
278,Slaking,,
|
|
||||||
279,Corphish,,
|
|
||||||
280,Crawdaunt,,
|
|
||||||
281,Igglybuff,,
|
|
||||||
282,Jigglypuff,,
|
|
||||||
283,Wigglytuff,,
|
|
||||||
284,Lickitung,,
|
|
||||||
285,Lickilicky,,
|
|
||||||
286,Yanma,,
|
|
||||||
287,Yanmega,,
|
|
||||||
288,Tropius,,
|
|
||||||
289,Carnivine,,
|
|
||||||
290,Croagunk,,
|
|
||||||
291,Toxicroak,,
|
|
||||||
292,Larvitar,,
|
|
||||||
293,Pupitar,,
|
|
||||||
294,Tyranitar,,
|
|
||||||
295,Reshiram,,
|
|
||||||
296,Zekrom,,
|
|
||||||
297,Kyurem,,
|
|
||||||
298,Keldeo,,
|
|
||||||
299,Meloetta,,
|
|
||||||
300,Genesect,,
|
|
||||||
|
@@ -1,157 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
0,Victini,,
|
|
||||||
1,Snivy,,
|
|
||||||
2,Servine,,
|
|
||||||
3,Serperior,,
|
|
||||||
4,Tepig,,
|
|
||||||
5,Pignite,,
|
|
||||||
6,Emboar,,
|
|
||||||
7,Oshawott,,
|
|
||||||
8,Dewott,,
|
|
||||||
9,Samurott,,
|
|
||||||
10,Patrat,,
|
|
||||||
11,Watchog,,
|
|
||||||
12,Lillipup,,
|
|
||||||
13,Herdier,,
|
|
||||||
14,Stoutland,,
|
|
||||||
15,Purrloin,,
|
|
||||||
16,Liepard,,
|
|
||||||
17,Pansage,,
|
|
||||||
18,Simisage,,
|
|
||||||
19,Pansear,,
|
|
||||||
20,Simisear,,
|
|
||||||
21,Panpour,,
|
|
||||||
22,Simipour,,
|
|
||||||
23,Munna,,
|
|
||||||
24,Musharna,,
|
|
||||||
25,Pidove,,
|
|
||||||
26,Tranquill,,
|
|
||||||
27,Unfezant,,
|
|
||||||
28,Blitzle,,
|
|
||||||
29,Zebstrika,,
|
|
||||||
30,Roggenrola,,
|
|
||||||
31,Boldore,,
|
|
||||||
32,Gigalith,,
|
|
||||||
33,Woobat,,
|
|
||||||
34,Swoobat,,
|
|
||||||
35,Drilbur,,
|
|
||||||
36,Excadrill,,
|
|
||||||
37,Audino,,
|
|
||||||
38,Timburr,,
|
|
||||||
39,Gurdurr,,
|
|
||||||
40,Conkeldurr,,
|
|
||||||
41,Tympole,,
|
|
||||||
42,Palpitoad,,
|
|
||||||
43,Seismitoad,,
|
|
||||||
44,Throh,,
|
|
||||||
45,Sawk,,
|
|
||||||
46,Sewaddle,,
|
|
||||||
47,Swadloon,,
|
|
||||||
48,Leavanny,,
|
|
||||||
49,Venipede,,
|
|
||||||
50,Whirlipede,,
|
|
||||||
51,Scolipede,,
|
|
||||||
52,Cottonee,,
|
|
||||||
53,Whimsicott,,
|
|
||||||
54,Petilil,,
|
|
||||||
55,Lilligant,,
|
|
||||||
56,Basculin,,
|
|
||||||
57,Sandile,,
|
|
||||||
58,Krokorok,,
|
|
||||||
59,Krookodile,,
|
|
||||||
60,Darumaka,,
|
|
||||||
61,Darmanitan,,
|
|
||||||
62,Maractus,,
|
|
||||||
63,Dwebble,,
|
|
||||||
64,Crustle,,
|
|
||||||
65,Scraggy,,
|
|
||||||
66,Scrafty,,
|
|
||||||
67,Sigilyph,,
|
|
||||||
68,Yamask,,
|
|
||||||
69,Cofagrigus,,
|
|
||||||
70,Tirtouga,,
|
|
||||||
71,Carracosta,,
|
|
||||||
72,Archen,,
|
|
||||||
73,Archeops,,
|
|
||||||
74,Trubbish,,
|
|
||||||
75,Garbodor,,
|
|
||||||
76,Zorua,,
|
|
||||||
77,Zoroark,,
|
|
||||||
78,Minccino,,
|
|
||||||
79,Cinccino,,
|
|
||||||
80,Gothita,,
|
|
||||||
81,Gothorita,,
|
|
||||||
82,Gothitelle,,
|
|
||||||
83,Solosis,,
|
|
||||||
84,Duosion,,
|
|
||||||
85,Reuniclus,,
|
|
||||||
86,Ducklett,,
|
|
||||||
87,Swanna,,
|
|
||||||
88,Vanillite,,
|
|
||||||
89,Vanillish,,
|
|
||||||
90,Vanilluxe,,
|
|
||||||
91,Deerling,,
|
|
||||||
92,Sawsbuck,,
|
|
||||||
93,Emolga,,
|
|
||||||
94,Karrablast,,
|
|
||||||
95,Escavalier,,
|
|
||||||
96,Foongus,,
|
|
||||||
97,Amoonguss,,
|
|
||||||
98,Frillish,,
|
|
||||||
99,Jellicent,,
|
|
||||||
100,Alomomola,,
|
|
||||||
101,Joltik,,
|
|
||||||
102,Galvantula,,
|
|
||||||
103,Ferroseed,,
|
|
||||||
104,Ferrothorn,,
|
|
||||||
105,Klink,,
|
|
||||||
106,Klang,,
|
|
||||||
107,Klinklang,,
|
|
||||||
108,Tynamo,,
|
|
||||||
109,Eelektrik,,
|
|
||||||
110,Eelektross,,
|
|
||||||
111,Elgyem,,
|
|
||||||
112,Beheeyem,,
|
|
||||||
113,Litwick,,
|
|
||||||
114,Lampent,,
|
|
||||||
115,Chandelure,,
|
|
||||||
116,Axew,,
|
|
||||||
117,Fraxure,,
|
|
||||||
118,Haxorus,,
|
|
||||||
119,Cubchoo,,
|
|
||||||
120,Beartic,,
|
|
||||||
121,Cryogonal,,
|
|
||||||
122,Shelmet,,
|
|
||||||
123,Accelgor,,
|
|
||||||
124,Stunfisk,,
|
|
||||||
125,Mienfoo,,
|
|
||||||
126,Mienshao,,
|
|
||||||
127,Druddigon,,
|
|
||||||
128,Golett,,
|
|
||||||
129,Golurk,,
|
|
||||||
130,Pawniard,,
|
|
||||||
131,Bisharp,,
|
|
||||||
132,Bouffalant,,
|
|
||||||
133,Rufflet,,
|
|
||||||
134,Braviary,,
|
|
||||||
135,Vullaby,,
|
|
||||||
136,Mandibuzz,,
|
|
||||||
137,Heatmor,,
|
|
||||||
138,Durant,,
|
|
||||||
139,Deino,,
|
|
||||||
140,Zweilous,,
|
|
||||||
141,Hydreigon,,
|
|
||||||
142,Larvesta,,
|
|
||||||
143,Volcarona,,
|
|
||||||
144,Cobalion,,
|
|
||||||
145,Terrakion,,
|
|
||||||
146,Virizion,,
|
|
||||||
147,Tornadus,,
|
|
||||||
148,Thundurus,,
|
|
||||||
149,Reshiram,,
|
|
||||||
150,Zekrom,,
|
|
||||||
151,Landorus,,
|
|
||||||
152,Kyurem,,
|
|
||||||
153,Keldeo,,
|
|
||||||
154,Meloetta,,
|
|
||||||
155,Genesect,,
|
|
||||||
|
@@ -1,152 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Turtwig,,
|
|
||||||
2,Grotle,,
|
|
||||||
3,Torterra,,
|
|
||||||
4,Chimchar,,
|
|
||||||
5,Monferno,,
|
|
||||||
6,Infernape,,
|
|
||||||
7,Piplup,,
|
|
||||||
8,Prinplup,,
|
|
||||||
9,Empoleon,,
|
|
||||||
10,Starly,,
|
|
||||||
11,Staravia,,
|
|
||||||
12,Staraptor,,
|
|
||||||
13,Bidoof,,
|
|
||||||
14,Bibarel,,
|
|
||||||
15,Kricketot,,
|
|
||||||
16,Kricketune,,
|
|
||||||
17,Shinx,,
|
|
||||||
18,Luxio,,
|
|
||||||
19,Luxray,,
|
|
||||||
20,Abra,,
|
|
||||||
21,Kadabra,,
|
|
||||||
22,Alakazam,,
|
|
||||||
23,Magikarp,,
|
|
||||||
24,Gyarados,,
|
|
||||||
25,Budew,,
|
|
||||||
26,Roselia,,
|
|
||||||
27,Roserade,,
|
|
||||||
28,Zubat,,
|
|
||||||
29,Golbat,,
|
|
||||||
30,Crobat,,
|
|
||||||
31,Geodude,,
|
|
||||||
32,Graveler,,
|
|
||||||
33,Golem,,
|
|
||||||
34,Onix,,
|
|
||||||
35,Steelix,,
|
|
||||||
36,Cranidos,,
|
|
||||||
37,Rampardos,,
|
|
||||||
38,Shieldon,,
|
|
||||||
39,Bastiodon,,
|
|
||||||
40,Machop,,
|
|
||||||
41,Machoke,,
|
|
||||||
42,Machamp,,
|
|
||||||
43,Psyduck,,
|
|
||||||
44,Golduck,,
|
|
||||||
45,Burmy,,
|
|
||||||
46,Wormadam,,
|
|
||||||
47,Mothim,,
|
|
||||||
48,Wurmple,,
|
|
||||||
49,Silcoon,,
|
|
||||||
50,Beautifly,,
|
|
||||||
51,Cascoon,,
|
|
||||||
52,Dustox,,
|
|
||||||
53,Combee,,
|
|
||||||
54,Vespiquen,,
|
|
||||||
55,Pachirisu,,
|
|
||||||
56,Buizel,,
|
|
||||||
57,Floatzel,,
|
|
||||||
58,Cherubi,,
|
|
||||||
59,Cherrim,,
|
|
||||||
60,Shellos,,
|
|
||||||
61,Gastrodon,,
|
|
||||||
62,Heracross,,
|
|
||||||
63,Aipom,,
|
|
||||||
64,Ambipom,,
|
|
||||||
65,Drifloon,,
|
|
||||||
66,Drifblim,,
|
|
||||||
67,Buneary,,
|
|
||||||
68,Lopunny,,
|
|
||||||
69,Gastly,,
|
|
||||||
70,Haunter,,
|
|
||||||
71,Gengar,,
|
|
||||||
72,Misdreavus,,
|
|
||||||
73,Mismagius,,
|
|
||||||
74,Murkrow,,
|
|
||||||
75,Honchkrow,,
|
|
||||||
76,Glameow,,
|
|
||||||
77,Purugly,,
|
|
||||||
78,Goldeen,,
|
|
||||||
79,Seaking,,
|
|
||||||
80,Barboach,,
|
|
||||||
81,Whiscash,,
|
|
||||||
82,Chingling,,
|
|
||||||
83,Chimecho,,
|
|
||||||
84,Stunky,,
|
|
||||||
85,Skuntank,,
|
|
||||||
86,Meditite,,
|
|
||||||
87,Medicham,,
|
|
||||||
88,Bronzor,,
|
|
||||||
89,Bronzong,,
|
|
||||||
90,Ponyta,,
|
|
||||||
91,Rapidash,,
|
|
||||||
92,Bonsly,,
|
|
||||||
93,Sudowoodo,,
|
|
||||||
94,Mime Jr.,,
|
|
||||||
95,Mr. Mime,,
|
|
||||||
96,Happiny,,
|
|
||||||
97,Chansey,,
|
|
||||||
98,Blissey,,
|
|
||||||
99,Cleffa,,
|
|
||||||
100,Clefairy,,
|
|
||||||
101,Clefable,,
|
|
||||||
102,Chatot,,
|
|
||||||
103,Pichu,,
|
|
||||||
104,Pikachu,,
|
|
||||||
105,Raichu,,
|
|
||||||
106,Hoothoot,,
|
|
||||||
107,Noctowl,,
|
|
||||||
108,Spiritomb,,
|
|
||||||
109,Gible,,
|
|
||||||
110,Gabite,,
|
|
||||||
111,Garchomp,,
|
|
||||||
112,Munchlax,,
|
|
||||||
113,Snorlax,,
|
|
||||||
114,Unown,,
|
|
||||||
115,Riolu,,
|
|
||||||
116,Lucario,,
|
|
||||||
117,Wooper,,
|
|
||||||
118,Quagsire,,
|
|
||||||
119,Wingull,,
|
|
||||||
120,Pelipper,,
|
|
||||||
121,Girafarig,,
|
|
||||||
122,Hippopotas,,
|
|
||||||
123,Hippowdon,,
|
|
||||||
124,Azurill,,
|
|
||||||
125,Marill,,
|
|
||||||
126,Azumarill,,
|
|
||||||
127,Skorupi,,
|
|
||||||
128,Drapion,,
|
|
||||||
129,Croagunk,,
|
|
||||||
130,Toxicroak,,
|
|
||||||
131,Carnivine,,
|
|
||||||
132,Remoraid,,
|
|
||||||
133,Octillery,,
|
|
||||||
134,Finneon,,
|
|
||||||
135,Lumineon,,
|
|
||||||
136,Tentacool,,
|
|
||||||
137,Tentacruel,,
|
|
||||||
138,Feebas,,
|
|
||||||
139,Milotic,,
|
|
||||||
140,Mantyke,,
|
|
||||||
141,Mantine,,
|
|
||||||
142,Snover,,
|
|
||||||
143,Abomasnow,,
|
|
||||||
144,Sneasel,,
|
|
||||||
145,Weavile,,
|
|
||||||
146,Uxie,,
|
|
||||||
147,Mesprit,,
|
|
||||||
148,Azelf,,
|
|
||||||
149,Dialga,,
|
|
||||||
150,Palkia,,
|
|
||||||
151,Manaphy,,
|
|
||||||
|
@@ -1,152 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Turtwig,,
|
|
||||||
2,Grotle,,
|
|
||||||
3,Torterra,,
|
|
||||||
4,Chimchar,,
|
|
||||||
5,Monferno,,
|
|
||||||
6,Infernape,,
|
|
||||||
7,Piplup,,
|
|
||||||
8,Prinplup,,
|
|
||||||
9,Empoleon,,
|
|
||||||
10,Starly,,
|
|
||||||
11,Staravia,,
|
|
||||||
12,Staraptor,,
|
|
||||||
13,Bidoof,,
|
|
||||||
14,Bibarel,,
|
|
||||||
15,Kricketot,,
|
|
||||||
16,Kricketune,,
|
|
||||||
17,Shinx,,
|
|
||||||
18,Luxio,,
|
|
||||||
19,Luxray,,
|
|
||||||
20,Abra,,
|
|
||||||
21,Kadabra,,
|
|
||||||
22,Alakazam,,
|
|
||||||
23,Magikarp,,
|
|
||||||
24,Gyarados,,
|
|
||||||
25,Budew,,
|
|
||||||
26,Roselia,,
|
|
||||||
27,Roserade,,
|
|
||||||
28,Zubat,,
|
|
||||||
29,Golbat,,
|
|
||||||
30,Crobat,,
|
|
||||||
31,Geodude,,
|
|
||||||
32,Graveler,,
|
|
||||||
33,Golem,,
|
|
||||||
34,Onix,,
|
|
||||||
35,Steelix,,
|
|
||||||
36,Cranidos,,
|
|
||||||
37,Rampardos,,
|
|
||||||
38,Shieldon,,
|
|
||||||
39,Bastiodon,,
|
|
||||||
40,Machop,,
|
|
||||||
41,Machoke,,
|
|
||||||
42,Machamp,,
|
|
||||||
43,Psyduck,,
|
|
||||||
44,Golduck,,
|
|
||||||
45,Burmy,,
|
|
||||||
46,Wormadam,,
|
|
||||||
47,Mothim,,
|
|
||||||
48,Wurmple,,
|
|
||||||
49,Silcoon,,
|
|
||||||
50,Beautifly,,
|
|
||||||
51,Cascoon,,
|
|
||||||
52,Dustox,,
|
|
||||||
53,Combee,,
|
|
||||||
54,Vespiquen,,
|
|
||||||
55,Pachirisu,,
|
|
||||||
56,Buizel,,
|
|
||||||
57,Floatzel,,
|
|
||||||
58,Cherubi,,
|
|
||||||
59,Cherrim,,
|
|
||||||
60,Shellos,,
|
|
||||||
61,Gastrodon,,
|
|
||||||
62,Heracross,,
|
|
||||||
63,Aipom,,
|
|
||||||
64,Ambipom,,
|
|
||||||
65,Drifloon,,
|
|
||||||
66,Drifblim,,
|
|
||||||
67,Buneary,,
|
|
||||||
68,Lopunny,,
|
|
||||||
69,Gastly,,
|
|
||||||
70,Haunter,,
|
|
||||||
71,Gengar,,
|
|
||||||
72,Misdreavus,,
|
|
||||||
73,Mismagius,,
|
|
||||||
74,Murkrow,,
|
|
||||||
75,Honchkrow,,
|
|
||||||
76,Glameow,,
|
|
||||||
77,Purugly,,
|
|
||||||
78,Goldeen,,
|
|
||||||
79,Seaking,,
|
|
||||||
80,Barboach,,
|
|
||||||
81,Whiscash,,
|
|
||||||
82,Chingling,,
|
|
||||||
83,Chimecho,,
|
|
||||||
84,Stunky,,
|
|
||||||
85,Skuntank,,
|
|
||||||
86,Meditite,,
|
|
||||||
87,Medicham,,
|
|
||||||
88,Bronzor,,
|
|
||||||
89,Bronzong,,
|
|
||||||
90,Ponyta,,
|
|
||||||
91,Rapidash,,
|
|
||||||
92,Bonsly,,
|
|
||||||
93,Sudowoodo,,
|
|
||||||
94,Mime Jr.,,
|
|
||||||
95,Mr. Mime,,
|
|
||||||
96,Happiny,,
|
|
||||||
97,Chansey,,
|
|
||||||
98,Blissey,,
|
|
||||||
99,Cleffa,,
|
|
||||||
100,Clefairy,,
|
|
||||||
101,Clefable,,
|
|
||||||
102,Chatot,,
|
|
||||||
103,Pichu,,
|
|
||||||
104,Pikachu,,
|
|
||||||
105,Raichu,,
|
|
||||||
106,Hoothoot,,
|
|
||||||
107,Noctowl,,
|
|
||||||
108,Spiritomb,,
|
|
||||||
109,Gible,,
|
|
||||||
110,Gabite,,
|
|
||||||
111,Garchomp,,
|
|
||||||
112,Munchlax,,
|
|
||||||
113,Snorlax,,
|
|
||||||
114,Unown,,
|
|
||||||
115,Riolu,,
|
|
||||||
116,Lucario,,
|
|
||||||
117,Wooper,,
|
|
||||||
118,Quagsire,,
|
|
||||||
119,Wingull,,
|
|
||||||
120,Pelipper,,
|
|
||||||
121,Girafarig,,
|
|
||||||
122,Hippopotas,,
|
|
||||||
123,Hippowdon,,
|
|
||||||
124,Azurill,,
|
|
||||||
125,Marill,,
|
|
||||||
126,Azumarill,,
|
|
||||||
127,Skorupi,,
|
|
||||||
128,Drapion,,
|
|
||||||
129,Croagunk,,
|
|
||||||
130,Toxicroak,,
|
|
||||||
131,Carnivine,,
|
|
||||||
132,Remoraid,,
|
|
||||||
133,Octillery,,
|
|
||||||
134,Finneon,,
|
|
||||||
135,Lumineon,,
|
|
||||||
136,Tentacool,,
|
|
||||||
137,Tentacruel,,
|
|
||||||
138,Feebas,,
|
|
||||||
139,Milotic,,
|
|
||||||
140,Mantyke,,
|
|
||||||
141,Mantine,,
|
|
||||||
142,Snover,,
|
|
||||||
143,Abomasnow,,
|
|
||||||
144,Sneasel,,
|
|
||||||
145,Weavile,,
|
|
||||||
146,Uxie,,
|
|
||||||
147,Mesprit,,
|
|
||||||
148,Azelf,,
|
|
||||||
149,Dialga,,
|
|
||||||
150,Palkia,,
|
|
||||||
151,Manaphy,,
|
|
||||||
|
@@ -1,152 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Bulbasaur,,
|
|
||||||
2,Ivysaur,,
|
|
||||||
3,Venusaur,,
|
|
||||||
4,Charmander,,
|
|
||||||
5,Charmeleon,,
|
|
||||||
6,Charizard,,
|
|
||||||
7,Squirtle,,
|
|
||||||
8,Wartortle,,
|
|
||||||
9,Blastoise,,
|
|
||||||
10,Caterpie,,
|
|
||||||
11,Metapod,,
|
|
||||||
12,Butterfree,,
|
|
||||||
13,Weedle,,
|
|
||||||
14,Kakuna,,
|
|
||||||
15,Beedrill,,
|
|
||||||
16,Pidgey,,
|
|
||||||
17,Pidgeotto,,
|
|
||||||
18,Pidgeot,,
|
|
||||||
19,Rattata,,
|
|
||||||
20,Raticate,,
|
|
||||||
21,Spearow,,
|
|
||||||
22,Fearow,,
|
|
||||||
23,Ekans,,
|
|
||||||
24,Arbok,,
|
|
||||||
25,Pikachu,,
|
|
||||||
26,Raichu,,
|
|
||||||
27,Sandshrew,,
|
|
||||||
28,Sandslash,,
|
|
||||||
29,Nidoran♀,,
|
|
||||||
30,Nidorina,,
|
|
||||||
31,Nidoqueen,,
|
|
||||||
32,Nidoran♂,,
|
|
||||||
33,Nidorino,,
|
|
||||||
34,Nidoking,,
|
|
||||||
35,Clefairy,,
|
|
||||||
36,Clefable,,
|
|
||||||
37,Vulpix,,
|
|
||||||
38,Ninetales,,
|
|
||||||
39,Jigglypuff,,
|
|
||||||
40,Wigglytuff,,
|
|
||||||
41,Zubat,,
|
|
||||||
42,Golbat,,
|
|
||||||
43,Oddish,,
|
|
||||||
44,Gloom,,
|
|
||||||
45,Vileplume,,
|
|
||||||
46,Paras,,
|
|
||||||
47,Parasect,,
|
|
||||||
48,Venonat,,
|
|
||||||
49,Venomoth,,
|
|
||||||
50,Diglett,,
|
|
||||||
51,Dugtrio,,
|
|
||||||
52,Meowth,,
|
|
||||||
53,Persian,,
|
|
||||||
54,Psyduck,,
|
|
||||||
55,Golduck,,
|
|
||||||
56,Mankey,,
|
|
||||||
57,Primeape,,
|
|
||||||
58,Growlithe,,
|
|
||||||
59,Arcanine,,
|
|
||||||
60,Poliwag,,
|
|
||||||
61,Poliwhirl,,
|
|
||||||
62,Poliwrath,,
|
|
||||||
63,Abra,,
|
|
||||||
64,Kadabra,,
|
|
||||||
65,Alakazam,,
|
|
||||||
66,Machop,,
|
|
||||||
67,Machoke,,
|
|
||||||
68,Machamp,,
|
|
||||||
69,Bellsprout,,
|
|
||||||
70,Weepinbell,,
|
|
||||||
71,Victreebel,,
|
|
||||||
72,Tentacool,,
|
|
||||||
73,Tentacruel,,
|
|
||||||
74,Geodude,,
|
|
||||||
75,Graveler,,
|
|
||||||
76,Golem,,
|
|
||||||
77,Ponyta,,
|
|
||||||
78,Rapidash,,
|
|
||||||
79,Slowpoke,,
|
|
||||||
80,Slowbro,,
|
|
||||||
81,Magnemite,,
|
|
||||||
82,Magneton,,
|
|
||||||
83,Farfetch’d,,
|
|
||||||
84,Doduo,,
|
|
||||||
85,Dodrio,,
|
|
||||||
86,Seel,,
|
|
||||||
87,Dewgong,,
|
|
||||||
88,Grimer,,
|
|
||||||
89,Muk,,
|
|
||||||
90,Shellder,,
|
|
||||||
91,Cloyster,,
|
|
||||||
92,Gastly,,
|
|
||||||
93,Haunter,,
|
|
||||||
94,Gengar,,
|
|
||||||
95,Onix,,
|
|
||||||
96,Drowzee,,
|
|
||||||
97,Hypno,,
|
|
||||||
98,Krabby,,
|
|
||||||
99,Kingler,,
|
|
||||||
100,Voltorb,,
|
|
||||||
101,Electrode,,
|
|
||||||
102,Exeggcute,,
|
|
||||||
103,Exeggutor,,
|
|
||||||
104,Cubone,,
|
|
||||||
105,Marowak,,
|
|
||||||
106,Hitmonlee,,
|
|
||||||
107,Hitmonchan,,
|
|
||||||
108,Lickitung,,
|
|
||||||
109,Koffing,,
|
|
||||||
110,Weezing,,
|
|
||||||
111,Rhyhorn,,
|
|
||||||
112,Rhydon,,
|
|
||||||
113,Chansey,,
|
|
||||||
114,Tangela,,
|
|
||||||
115,Kangaskhan,,
|
|
||||||
116,Horsea,,
|
|
||||||
117,Seadra,,
|
|
||||||
118,Goldeen,,
|
|
||||||
119,Seaking,,
|
|
||||||
120,Staryu,,
|
|
||||||
121,Starmie,,
|
|
||||||
122,Mr. Mime,,
|
|
||||||
123,Scyther,,
|
|
||||||
124,Jynx,,
|
|
||||||
125,Electabuzz,,
|
|
||||||
126,Magmar,,
|
|
||||||
127,Pinsir,,
|
|
||||||
128,Tauros,,
|
|
||||||
129,Magikarp,,
|
|
||||||
130,Gyarados,,
|
|
||||||
131,Lapras,,
|
|
||||||
132,Ditto,,
|
|
||||||
133,Eevee,,
|
|
||||||
134,Vaporeon,,
|
|
||||||
135,Jolteon,,
|
|
||||||
136,Flareon,,
|
|
||||||
137,Porygon,,
|
|
||||||
138,Omanyte,,
|
|
||||||
139,Omastar,,
|
|
||||||
140,Kabuto,,
|
|
||||||
141,Kabutops,,
|
|
||||||
142,Aerodactyl,,
|
|
||||||
143,Snorlax,,
|
|
||||||
144,Articuno,,
|
|
||||||
145,Zapdos,,
|
|
||||||
146,Moltres,,
|
|
||||||
147,Dratini,,
|
|
||||||
148,Dragonair,,
|
|
||||||
149,Dragonite,,
|
|
||||||
150,Mewtwo,,
|
|
||||||
151,Mew,,
|
|
||||||
|
@@ -1,252 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Chikorita,,
|
|
||||||
2,Bayleef,,
|
|
||||||
3,Meganium,,
|
|
||||||
4,Cyndaquil,,
|
|
||||||
5,Quilava,,
|
|
||||||
6,Typhlosion,,
|
|
||||||
7,Totodile,,
|
|
||||||
8,Croconaw,,
|
|
||||||
9,Feraligatr,,
|
|
||||||
10,Pidgey,,
|
|
||||||
11,Pidgeotto,,
|
|
||||||
12,Pidgeot,,
|
|
||||||
13,Spearow,,
|
|
||||||
14,Fearow,,
|
|
||||||
15,Hoothoot,,
|
|
||||||
16,Noctowl,,
|
|
||||||
17,Rattata,,
|
|
||||||
18,Raticate,,
|
|
||||||
19,Sentret,,
|
|
||||||
20,Furret,,
|
|
||||||
21,Pichu,,
|
|
||||||
22,Pikachu,,
|
|
||||||
23,Raichu,,
|
|
||||||
24,Caterpie,,
|
|
||||||
25,Metapod,,
|
|
||||||
26,Butterfree,,
|
|
||||||
27,Weedle,,
|
|
||||||
28,Kakuna,,
|
|
||||||
29,Beedrill,,
|
|
||||||
30,Ledyba,,
|
|
||||||
31,Ledian,,
|
|
||||||
32,Spinarak,,
|
|
||||||
33,Ariados,,
|
|
||||||
34,Geodude,,
|
|
||||||
35,Graveler,,
|
|
||||||
36,Golem,,
|
|
||||||
37,Zubat,,
|
|
||||||
38,Golbat,,
|
|
||||||
39,Crobat,,
|
|
||||||
40,Cleffa,,
|
|
||||||
41,Clefairy,,
|
|
||||||
42,Clefable,,
|
|
||||||
43,Igglybuff,,
|
|
||||||
44,Jigglypuff,,
|
|
||||||
45,Wigglytuff,,
|
|
||||||
46,Togepi,,
|
|
||||||
47,Togetic,,
|
|
||||||
48,Sandshrew,,
|
|
||||||
49,Sandslash,,
|
|
||||||
50,Ekans,,
|
|
||||||
51,Arbok,,
|
|
||||||
52,Dunsparce,,
|
|
||||||
53,Mareep,,
|
|
||||||
54,Flaaffy,,
|
|
||||||
55,Ampharos,,
|
|
||||||
56,Wooper,,
|
|
||||||
57,Quagsire,,
|
|
||||||
58,Gastly,,
|
|
||||||
59,Haunter,,
|
|
||||||
60,Gengar,,
|
|
||||||
61,Unown,,
|
|
||||||
62,Onix,,
|
|
||||||
63,Steelix,,
|
|
||||||
64,Bellsprout,,
|
|
||||||
65,Weepinbell,,
|
|
||||||
66,Victreebel,,
|
|
||||||
67,Hoppip,,
|
|
||||||
68,Skiploom,,
|
|
||||||
69,Jumpluff,,
|
|
||||||
70,Paras,,
|
|
||||||
71,Parasect,,
|
|
||||||
72,Poliwag,,
|
|
||||||
73,Poliwhirl,,
|
|
||||||
74,Poliwrath,,
|
|
||||||
75,Politoed,,
|
|
||||||
76,Magikarp,,
|
|
||||||
77,Gyarados,,
|
|
||||||
78,Goldeen,,
|
|
||||||
79,Seaking,,
|
|
||||||
80,Slowpoke,,
|
|
||||||
81,Slowbro,,
|
|
||||||
82,Slowking,,
|
|
||||||
83,Oddish,,
|
|
||||||
84,Gloom,,
|
|
||||||
85,Vileplume,,
|
|
||||||
86,Bellossom,,
|
|
||||||
87,Drowzee,,
|
|
||||||
88,Hypno,,
|
|
||||||
89,Abra,,
|
|
||||||
90,Kadabra,,
|
|
||||||
91,Alakazam,,
|
|
||||||
92,Ditto,,
|
|
||||||
93,Pineco,,
|
|
||||||
94,Forretress,,
|
|
||||||
95,Nidoran♀,,
|
|
||||||
96,Nidorina,,
|
|
||||||
97,Nidoqueen,,
|
|
||||||
98,Nidoran♂,,
|
|
||||||
99,Nidorino,,
|
|
||||||
100,Nidoking,,
|
|
||||||
101,Yanma,,
|
|
||||||
102,Sunkern,,
|
|
||||||
103,Sunflora,,
|
|
||||||
104,Exeggcute,,
|
|
||||||
105,Exeggutor,,
|
|
||||||
106,Sudowoodo,,
|
|
||||||
107,Wobbuffet,,
|
|
||||||
108,Venonat,,
|
|
||||||
109,Venomoth,,
|
|
||||||
110,Scyther,,
|
|
||||||
111,Scizor,,
|
|
||||||
112,Pinsir,,
|
|
||||||
113,Heracross,,
|
|
||||||
114,Koffing,,
|
|
||||||
115,Weezing,,
|
|
||||||
116,Grimer,,
|
|
||||||
117,Muk,,
|
|
||||||
118,Magnemite,,
|
|
||||||
119,Magneton,,
|
|
||||||
120,Voltorb,,
|
|
||||||
121,Electrode,,
|
|
||||||
122,Aipom,,
|
|
||||||
123,Snubbull,,
|
|
||||||
124,Granbull,,
|
|
||||||
125,Vulpix,,
|
|
||||||
126,Ninetales,,
|
|
||||||
127,Growlithe,,
|
|
||||||
128,Arcanine,,
|
|
||||||
129,Stantler,,
|
|
||||||
130,Marill,,
|
|
||||||
131,Azumarill,,
|
|
||||||
132,Diglett,,
|
|
||||||
133,Dugtrio,,
|
|
||||||
134,Mankey,,
|
|
||||||
135,Primeape,,
|
|
||||||
136,Meowth,,
|
|
||||||
137,Persian,,
|
|
||||||
138,Psyduck,,
|
|
||||||
139,Golduck,,
|
|
||||||
140,Machop,,
|
|
||||||
141,Machoke,,
|
|
||||||
142,Machamp,,
|
|
||||||
143,Tyrogue,,
|
|
||||||
144,Hitmonlee,,
|
|
||||||
145,Hitmonchan,,
|
|
||||||
146,Hitmontop,,
|
|
||||||
147,Girafarig,,
|
|
||||||
148,Tauros,,
|
|
||||||
149,Miltank,,
|
|
||||||
150,Magby,,
|
|
||||||
151,Magmar,,
|
|
||||||
152,Smoochum,,
|
|
||||||
153,Jynx,,
|
|
||||||
154,Elekid,,
|
|
||||||
155,Electabuzz,,
|
|
||||||
156,Mr. Mime,,
|
|
||||||
157,Smeargle,,
|
|
||||||
158,Farfetch’d,,
|
|
||||||
159,Natu,,
|
|
||||||
160,Xatu,,
|
|
||||||
161,Qwilfish,,
|
|
||||||
162,Tentacool,,
|
|
||||||
163,Tentacruel,,
|
|
||||||
164,Krabby,,
|
|
||||||
165,Kingler,,
|
|
||||||
166,Shuckle,,
|
|
||||||
167,Staryu,,
|
|
||||||
168,Starmie,,
|
|
||||||
169,Shellder,,
|
|
||||||
170,Cloyster,,
|
|
||||||
171,Corsola,,
|
|
||||||
172,Remoraid,,
|
|
||||||
173,Octillery,,
|
|
||||||
174,Chinchou,,
|
|
||||||
175,Lanturn,,
|
|
||||||
176,Seel,,
|
|
||||||
177,Dewgong,,
|
|
||||||
178,Lickitung,,
|
|
||||||
179,Tangela,,
|
|
||||||
180,Eevee,,
|
|
||||||
181,Vaporeon,,
|
|
||||||
182,Jolteon,,
|
|
||||||
183,Flareon,,
|
|
||||||
184,Espeon,,
|
|
||||||
185,Umbreon,,
|
|
||||||
186,Horsea,,
|
|
||||||
187,Seadra,,
|
|
||||||
188,Kingdra,,
|
|
||||||
189,Gligar,,
|
|
||||||
190,Delibird,,
|
|
||||||
191,Swinub,,
|
|
||||||
192,Piloswine,,
|
|
||||||
193,Teddiursa,,
|
|
||||||
194,Ursaring,,
|
|
||||||
195,Phanpy,,
|
|
||||||
196,Donphan,,
|
|
||||||
197,Mantine,,
|
|
||||||
198,Skarmory,,
|
|
||||||
199,Doduo,,
|
|
||||||
200,Dodrio,,
|
|
||||||
201,Ponyta,,
|
|
||||||
202,Rapidash,,
|
|
||||||
203,Cubone,,
|
|
||||||
204,Marowak,,
|
|
||||||
205,Kangaskhan,,
|
|
||||||
206,Rhyhorn,,
|
|
||||||
207,Rhydon,,
|
|
||||||
208,Murkrow,,
|
|
||||||
209,Houndour,,
|
|
||||||
210,Houndoom,,
|
|
||||||
211,Slugma,,
|
|
||||||
212,Magcargo,,
|
|
||||||
213,Sneasel,,
|
|
||||||
214,Misdreavus,,
|
|
||||||
215,Porygon,,
|
|
||||||
216,Porygon2,,
|
|
||||||
217,Chansey,,
|
|
||||||
218,Blissey,,
|
|
||||||
219,Lapras,,
|
|
||||||
220,Omanyte,,
|
|
||||||
221,Omastar,,
|
|
||||||
222,Kabuto,,
|
|
||||||
223,Kabutops,,
|
|
||||||
224,Aerodactyl,,
|
|
||||||
225,Snorlax,,
|
|
||||||
226,Bulbasaur,,
|
|
||||||
227,Ivysaur,,
|
|
||||||
228,Venusaur,,
|
|
||||||
229,Charmander,,
|
|
||||||
230,Charmeleon,,
|
|
||||||
231,Charizard,,
|
|
||||||
232,Squirtle,,
|
|
||||||
233,Wartortle,,
|
|
||||||
234,Blastoise,,
|
|
||||||
235,Articuno,,
|
|
||||||
236,Zapdos,,
|
|
||||||
237,Moltres,,
|
|
||||||
238,Raikou,,
|
|
||||||
239,Entei,,
|
|
||||||
240,Suicune,,
|
|
||||||
241,Dratini,,
|
|
||||||
242,Dragonair,,
|
|
||||||
243,Dragonite,,
|
|
||||||
244,Larvitar,,
|
|
||||||
245,Pupitar,,
|
|
||||||
246,Tyranitar,,
|
|
||||||
247,Lugia,,
|
|
||||||
248,Ho-Oh,,
|
|
||||||
249,Mewtwo,,
|
|
||||||
250,Mew,,
|
|
||||||
251,Celebi,,
|
|
||||||
|
@@ -1,257 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Chikorita,,
|
|
||||||
2,Bayleef,,
|
|
||||||
3,Meganium,,
|
|
||||||
4,Cyndaquil,,
|
|
||||||
5,Quilava,,
|
|
||||||
6,Typhlosion,,
|
|
||||||
7,Totodile,,
|
|
||||||
8,Croconaw,,
|
|
||||||
9,Feraligatr,,
|
|
||||||
10,Pidgey,,
|
|
||||||
11,Pidgeotto,,
|
|
||||||
12,Pidgeot,,
|
|
||||||
13,Spearow,,
|
|
||||||
14,Fearow,,
|
|
||||||
15,Hoothoot,,
|
|
||||||
16,Noctowl,,
|
|
||||||
17,Rattata,,
|
|
||||||
18,Raticate,,
|
|
||||||
19,Sentret,,
|
|
||||||
20,Furret,,
|
|
||||||
21,Pichu,,
|
|
||||||
22,Pikachu,,
|
|
||||||
23,Raichu,,
|
|
||||||
24,Caterpie,,
|
|
||||||
25,Metapod,,
|
|
||||||
26,Butterfree,,
|
|
||||||
27,Weedle,,
|
|
||||||
28,Kakuna,,
|
|
||||||
29,Beedrill,,
|
|
||||||
30,Ledyba,,
|
|
||||||
31,Ledian,,
|
|
||||||
32,Spinarak,,
|
|
||||||
33,Ariados,,
|
|
||||||
34,Geodude,,
|
|
||||||
35,Graveler,,
|
|
||||||
36,Golem,,
|
|
||||||
37,Zubat,,
|
|
||||||
38,Golbat,,
|
|
||||||
39,Crobat,,
|
|
||||||
40,Cleffa,,
|
|
||||||
41,Clefairy,,
|
|
||||||
42,Clefable,,
|
|
||||||
43,Igglybuff,,
|
|
||||||
44,Jigglypuff,,
|
|
||||||
45,Wigglytuff,,
|
|
||||||
46,Togepi,,
|
|
||||||
47,Togetic,,
|
|
||||||
48,Sandshrew,,
|
|
||||||
49,Sandslash,,
|
|
||||||
50,Ekans,,
|
|
||||||
51,Arbok,,
|
|
||||||
52,Dunsparce,,
|
|
||||||
53,Mareep,,
|
|
||||||
54,Flaaffy,,
|
|
||||||
55,Ampharos,,
|
|
||||||
56,Wooper,,
|
|
||||||
57,Quagsire,,
|
|
||||||
58,Gastly,,
|
|
||||||
59,Haunter,,
|
|
||||||
60,Gengar,,
|
|
||||||
61,Unown,,
|
|
||||||
62,Onix,,
|
|
||||||
63,Steelix,,
|
|
||||||
64,Bellsprout,,
|
|
||||||
65,Weepinbell,,
|
|
||||||
66,Victreebel,,
|
|
||||||
67,Hoppip,,
|
|
||||||
68,Skiploom,,
|
|
||||||
69,Jumpluff,,
|
|
||||||
70,Paras,,
|
|
||||||
71,Parasect,,
|
|
||||||
72,Poliwag,,
|
|
||||||
73,Poliwhirl,,
|
|
||||||
74,Poliwrath,,
|
|
||||||
75,Politoed,,
|
|
||||||
76,Magikarp,,
|
|
||||||
77,Gyarados,,
|
|
||||||
78,Goldeen,,
|
|
||||||
79,Seaking,,
|
|
||||||
80,Slowpoke,,
|
|
||||||
81,Slowbro,,
|
|
||||||
82,Slowking,,
|
|
||||||
83,Oddish,,
|
|
||||||
84,Gloom,,
|
|
||||||
85,Vileplume,,
|
|
||||||
86,Bellossom,,
|
|
||||||
87,Drowzee,,
|
|
||||||
88,Hypno,,
|
|
||||||
89,Abra,,
|
|
||||||
90,Kadabra,,
|
|
||||||
91,Alakazam,,
|
|
||||||
92,Ditto,,
|
|
||||||
93,Pineco,,
|
|
||||||
94,Forretress,,
|
|
||||||
95,Nidoran♀,,
|
|
||||||
96,Nidorina,,
|
|
||||||
97,Nidoqueen,,
|
|
||||||
98,Nidoran♂,,
|
|
||||||
99,Nidorino,,
|
|
||||||
100,Nidoking,,
|
|
||||||
101,Yanma,,
|
|
||||||
102,Yanmega,,
|
|
||||||
103,Sunkern,,
|
|
||||||
104,Sunflora,,
|
|
||||||
105,Exeggcute,,
|
|
||||||
106,Exeggutor,,
|
|
||||||
107,Sudowoodo,,
|
|
||||||
108,Wobbuffet,,
|
|
||||||
109,Venonat,,
|
|
||||||
110,Venomoth,,
|
|
||||||
111,Scyther,,
|
|
||||||
112,Scizor,,
|
|
||||||
113,Pinsir,,
|
|
||||||
114,Heracross,,
|
|
||||||
115,Koffing,,
|
|
||||||
116,Weezing,,
|
|
||||||
117,Grimer,,
|
|
||||||
118,Muk,,
|
|
||||||
119,Magnemite,,
|
|
||||||
120,Magneton,,
|
|
||||||
121,Voltorb,,
|
|
||||||
122,Electrode,,
|
|
||||||
123,Aipom,,
|
|
||||||
124,Ambipom,,
|
|
||||||
125,Snubbull,,
|
|
||||||
126,Granbull,,
|
|
||||||
127,Vulpix,,
|
|
||||||
128,Ninetales,,
|
|
||||||
129,Growlithe,,
|
|
||||||
130,Arcanine,,
|
|
||||||
131,Stantler,,
|
|
||||||
132,Marill,,
|
|
||||||
133,Azumarill,,
|
|
||||||
134,Diglett,,
|
|
||||||
135,Dugtrio,,
|
|
||||||
136,Mankey,,
|
|
||||||
137,Primeape,,
|
|
||||||
138,Meowth,,
|
|
||||||
139,Persian,,
|
|
||||||
140,Psyduck,,
|
|
||||||
141,Golduck,,
|
|
||||||
142,Machop,,
|
|
||||||
143,Machoke,,
|
|
||||||
144,Machamp,,
|
|
||||||
145,Tyrogue,,
|
|
||||||
146,Hitmonlee,,
|
|
||||||
147,Hitmonchan,,
|
|
||||||
148,Hitmontop,,
|
|
||||||
149,Girafarig,,
|
|
||||||
150,Tauros,,
|
|
||||||
151,Miltank,,
|
|
||||||
152,Magby,,
|
|
||||||
153,Magmar,,
|
|
||||||
154,Smoochum,,
|
|
||||||
155,Jynx,,
|
|
||||||
156,Elekid,,
|
|
||||||
157,Electabuzz,,
|
|
||||||
158,Mr. Mime,,
|
|
||||||
159,Smeargle,,
|
|
||||||
160,Farfetch’d,,
|
|
||||||
161,Natu,,
|
|
||||||
162,Xatu,,
|
|
||||||
163,Qwilfish,,
|
|
||||||
164,Tentacool,,
|
|
||||||
165,Tentacruel,,
|
|
||||||
166,Krabby,,
|
|
||||||
167,Kingler,,
|
|
||||||
168,Shuckle,,
|
|
||||||
169,Staryu,,
|
|
||||||
170,Starmie,,
|
|
||||||
171,Shellder,,
|
|
||||||
172,Cloyster,,
|
|
||||||
173,Corsola,,
|
|
||||||
174,Remoraid,,
|
|
||||||
175,Octillery,,
|
|
||||||
176,Chinchou,,
|
|
||||||
177,Lanturn,,
|
|
||||||
178,Seel,,
|
|
||||||
179,Dewgong,,
|
|
||||||
180,Lickitung,,
|
|
||||||
181,Lickilicky,,
|
|
||||||
182,Tangela,,
|
|
||||||
183,Tangrowth,,
|
|
||||||
184,Eevee,,
|
|
||||||
185,Vaporeon,,
|
|
||||||
186,Jolteon,,
|
|
||||||
187,Flareon,,
|
|
||||||
188,Espeon,,
|
|
||||||
189,Umbreon,,
|
|
||||||
190,Horsea,,
|
|
||||||
191,Seadra,,
|
|
||||||
192,Kingdra,,
|
|
||||||
193,Gligar,,
|
|
||||||
194,Delibird,,
|
|
||||||
195,Swinub,,
|
|
||||||
196,Piloswine,,
|
|
||||||
197,Mamoswine,,
|
|
||||||
198,Teddiursa,,
|
|
||||||
199,Ursaring,,
|
|
||||||
200,Phanpy,,
|
|
||||||
201,Donphan,,
|
|
||||||
202,Mantine,,
|
|
||||||
203,Skarmory,,
|
|
||||||
204,Doduo,,
|
|
||||||
205,Dodrio,,
|
|
||||||
206,Ponyta,,
|
|
||||||
207,Rapidash,,
|
|
||||||
208,Cubone,,
|
|
||||||
209,Marowak,,
|
|
||||||
210,Kangaskhan,,
|
|
||||||
211,Rhyhorn,,
|
|
||||||
212,Rhydon,,
|
|
||||||
213,Murkrow,,
|
|
||||||
214,Houndour,,
|
|
||||||
215,Houndoom,,
|
|
||||||
216,Slugma,,
|
|
||||||
217,Magcargo,,
|
|
||||||
218,Sneasel,,
|
|
||||||
219,Misdreavus,,
|
|
||||||
220,Porygon,,
|
|
||||||
221,Porygon2,,
|
|
||||||
222,Chansey,,
|
|
||||||
223,Blissey,,
|
|
||||||
224,Lapras,,
|
|
||||||
225,Omanyte,,
|
|
||||||
226,Omastar,,
|
|
||||||
227,Kabuto,,
|
|
||||||
228,Kabutops,,
|
|
||||||
229,Aerodactyl,,
|
|
||||||
230,Snorlax,,
|
|
||||||
231,Bulbasaur,,
|
|
||||||
232,Ivysaur,,
|
|
||||||
233,Venusaur,,
|
|
||||||
234,Charmander,,
|
|
||||||
235,Charmeleon,,
|
|
||||||
236,Charizard,,
|
|
||||||
237,Squirtle,,
|
|
||||||
238,Wartortle,,
|
|
||||||
239,Blastoise,,
|
|
||||||
240,Articuno,,
|
|
||||||
241,Zapdos,,
|
|
||||||
242,Moltres,,
|
|
||||||
243,Raikou,,
|
|
||||||
244,Entei,,
|
|
||||||
245,Suicune,,
|
|
||||||
246,Dratini,,
|
|
||||||
247,Dragonair,,
|
|
||||||
248,Dragonite,,
|
|
||||||
249,Larvitar,,
|
|
||||||
250,Pupitar,,
|
|
||||||
251,Tyranitar,,
|
|
||||||
252,Lugia,,
|
|
||||||
253,Ho-Oh,,
|
|
||||||
254,Mewtwo,,
|
|
||||||
255,Mew,,
|
|
||||||
256,Celebi,,
|
|
||||||
|
@@ -1,243 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Rowlet,,
|
|
||||||
2,Dartrix,,
|
|
||||||
3,Decidueye,,
|
|
||||||
4,Cyndaquil,,
|
|
||||||
5,Quilava,,
|
|
||||||
6,Typhlosion,,
|
|
||||||
7,Oshawott,,
|
|
||||||
8,Dewott,,
|
|
||||||
9,Samurott,,
|
|
||||||
10,Bidoof,,
|
|
||||||
11,Bibarel,,
|
|
||||||
12,Starly,,
|
|
||||||
13,Staravia,,
|
|
||||||
14,Staraptor,,
|
|
||||||
15,Shinx,,
|
|
||||||
16,Luxio,,
|
|
||||||
17,Luxray,,
|
|
||||||
18,Wurmple,,
|
|
||||||
19,Silcoon,,
|
|
||||||
20,Beautifly,,
|
|
||||||
21,Cascoon,,
|
|
||||||
22,Dustox,,
|
|
||||||
23,Ponyta,,
|
|
||||||
24,Rapidash,,
|
|
||||||
25,Eevee,,
|
|
||||||
26,Vaporeon,,
|
|
||||||
27,Jolteon,,
|
|
||||||
28,Flareon,,
|
|
||||||
29,Espeon,,
|
|
||||||
30,Umbreon,,
|
|
||||||
31,Leafeon,,
|
|
||||||
32,Glaceon,,
|
|
||||||
33,Sylveon,,
|
|
||||||
34,Zubat,,
|
|
||||||
35,Golbat,,
|
|
||||||
36,Crobat,,
|
|
||||||
37,Drifloon,,
|
|
||||||
38,Drifblim,,
|
|
||||||
39,Kricketot,,
|
|
||||||
40,Kricketune,,
|
|
||||||
41,Buizel,,
|
|
||||||
42,Floatzel,,
|
|
||||||
43,Burmy,,
|
|
||||||
44,Wormadam,,
|
|
||||||
45,Mothim,,
|
|
||||||
46,Geodude,,
|
|
||||||
47,Graveler,,
|
|
||||||
48,Golem,,
|
|
||||||
49,Stantler,,
|
|
||||||
50,Wyrdeer,,
|
|
||||||
51,Munchlax,,
|
|
||||||
52,Snorlax,,
|
|
||||||
53,Paras,,
|
|
||||||
54,Parasect,,
|
|
||||||
55,Pichu,,
|
|
||||||
56,Pikachu,,
|
|
||||||
57,Raichu,,
|
|
||||||
58,Abra,,
|
|
||||||
59,Kadabra,,
|
|
||||||
60,Alakazam,,
|
|
||||||
61,Chimchar,,
|
|
||||||
62,Monferno,,
|
|
||||||
63,Infernape,,
|
|
||||||
64,Buneary,,
|
|
||||||
65,Lopunny,,
|
|
||||||
66,Cherubi,,
|
|
||||||
67,Cherrim,,
|
|
||||||
68,Psyduck,,
|
|
||||||
69,Golduck,,
|
|
||||||
70,Combee,,
|
|
||||||
71,Vespiquen,,
|
|
||||||
72,Scyther,,
|
|
||||||
73,Kleavor,,
|
|
||||||
74,Scizor,,
|
|
||||||
75,Heracross,,
|
|
||||||
76,Mime Jr.,,
|
|
||||||
77,Mr. Mime,,
|
|
||||||
78,Aipom,,
|
|
||||||
79,Ambipom,,
|
|
||||||
80,Magikarp,,
|
|
||||||
81,Gyarados,,
|
|
||||||
82,Shellos,,
|
|
||||||
83,Gastrodon,,
|
|
||||||
84,Qwilfish,,
|
|
||||||
85,Overqwil,,
|
|
||||||
86,Happiny,,
|
|
||||||
87,Chansey,,
|
|
||||||
88,Blissey,,
|
|
||||||
89,Budew,,
|
|
||||||
90,Roselia,,
|
|
||||||
91,Roserade,,
|
|
||||||
92,Carnivine,,
|
|
||||||
93,Petilil,,
|
|
||||||
94,Lilligant,,
|
|
||||||
95,Tangela,,
|
|
||||||
96,Tangrowth,,
|
|
||||||
97,Barboach,,
|
|
||||||
98,Whiscash,,
|
|
||||||
99,Croagunk,,
|
|
||||||
100,Toxicroak,,
|
|
||||||
101,Ralts,,
|
|
||||||
102,Kirlia,,
|
|
||||||
103,Gardevoir,,
|
|
||||||
104,Gallade,,
|
|
||||||
105,Yanma,,
|
|
||||||
106,Yanmega,,
|
|
||||||
107,Hippopotas,,
|
|
||||||
108,Hippowdon,,
|
|
||||||
109,Pachirisu,,
|
|
||||||
110,Stunky,,
|
|
||||||
111,Skuntank,,
|
|
||||||
112,Teddiursa,,
|
|
||||||
113,Ursaring,,
|
|
||||||
114,Ursaluna,,
|
|
||||||
115,Goomy,,
|
|
||||||
116,Sliggoo,,
|
|
||||||
117,Goodra,,
|
|
||||||
118,Onix,,
|
|
||||||
119,Steelix,,
|
|
||||||
120,Rhyhorn,,
|
|
||||||
121,Rhydon,,
|
|
||||||
122,Rhyperior,,
|
|
||||||
123,Bonsly,,
|
|
||||||
124,Sudowoodo,,
|
|
||||||
125,Lickitung,,
|
|
||||||
126,Lickilicky,,
|
|
||||||
127,Togepi,,
|
|
||||||
128,Togetic,,
|
|
||||||
129,Togekiss,,
|
|
||||||
130,Turtwig,,
|
|
||||||
131,Grotle,,
|
|
||||||
132,Torterra,,
|
|
||||||
133,Porygon,,
|
|
||||||
134,Porygon2,,
|
|
||||||
135,Porygon-Z,,
|
|
||||||
136,Gastly,,
|
|
||||||
137,Haunter,,
|
|
||||||
138,Gengar,,
|
|
||||||
139,Spiritomb,,
|
|
||||||
140,Murkrow,,
|
|
||||||
141,Honchkrow,,
|
|
||||||
142,Unown,,
|
|
||||||
143,Spheal,,
|
|
||||||
144,Sealeo,,
|
|
||||||
145,Walrein,,
|
|
||||||
146,Remoraid,,
|
|
||||||
147,Octillery,,
|
|
||||||
148,Skorupi,,
|
|
||||||
149,Drapion,,
|
|
||||||
150,Growlithe,,
|
|
||||||
151,Arcanine,,
|
|
||||||
152,Glameow,,
|
|
||||||
153,Purugly,,
|
|
||||||
154,Machop,,
|
|
||||||
155,Machoke,,
|
|
||||||
156,Machamp,,
|
|
||||||
157,Chatot,,
|
|
||||||
158,Duskull,,
|
|
||||||
159,Dusclops,,
|
|
||||||
160,Dusknoir,,
|
|
||||||
161,Piplup,,
|
|
||||||
162,Prinplup,,
|
|
||||||
163,Empoleon,,
|
|
||||||
164,Mantyke,,
|
|
||||||
165,Mantine,,
|
|
||||||
166,Basculin,,
|
|
||||||
167,Basculegion,,
|
|
||||||
168,Vulpix,,
|
|
||||||
169,Ninetales,,
|
|
||||||
170,Tentacool,,
|
|
||||||
171,Tentacruel,,
|
|
||||||
172,Finneon,,
|
|
||||||
173,Lumineon,,
|
|
||||||
174,Magby,,
|
|
||||||
175,Magmar,,
|
|
||||||
176,Magmortar,,
|
|
||||||
177,Magnemite,,
|
|
||||||
178,Magneton,,
|
|
||||||
179,Magnezone,,
|
|
||||||
180,Bronzor,,
|
|
||||||
181,Bronzong,,
|
|
||||||
182,Elekid,,
|
|
||||||
183,Electabuzz,,
|
|
||||||
184,Electivire,,
|
|
||||||
185,Gligar,,
|
|
||||||
186,Gliscor,,
|
|
||||||
187,Gible,,
|
|
||||||
188,Gabite,,
|
|
||||||
189,Garchomp,,
|
|
||||||
190,Nosepass,,
|
|
||||||
191,Probopass,,
|
|
||||||
192,Voltorb,,
|
|
||||||
193,Electrode,,
|
|
||||||
194,Rotom,,
|
|
||||||
195,Chingling,,
|
|
||||||
196,Chimecho,,
|
|
||||||
197,Misdreavus,,
|
|
||||||
198,Mismagius,,
|
|
||||||
199,Cleffa,,
|
|
||||||
200,Clefairy,,
|
|
||||||
201,Clefable,,
|
|
||||||
202,Sneasel,,
|
|
||||||
203,Sneasler,,
|
|
||||||
204,Weavile,,
|
|
||||||
205,Snorunt,,
|
|
||||||
206,Glalie,,
|
|
||||||
207,Froslass,,
|
|
||||||
208,Cranidos,,
|
|
||||||
209,Rampardos,,
|
|
||||||
210,Shieldon,,
|
|
||||||
211,Bastiodon,,
|
|
||||||
212,Swinub,,
|
|
||||||
213,Piloswine,,
|
|
||||||
214,Mamoswine,,
|
|
||||||
215,Bergmite,,
|
|
||||||
216,Avalugg,,
|
|
||||||
217,Snover,,
|
|
||||||
218,Abomasnow,,
|
|
||||||
219,Zorua,,
|
|
||||||
220,Zoroark,,
|
|
||||||
221,Rufflet,,
|
|
||||||
222,Braviary,,
|
|
||||||
223,Riolu,,
|
|
||||||
224,Lucario,,
|
|
||||||
225,Uxie,,
|
|
||||||
226,Mesprit,,
|
|
||||||
227,Azelf,,
|
|
||||||
228,Heatran,,
|
|
||||||
229,Regigigas,,
|
|
||||||
230,Cresselia,,
|
|
||||||
231,Tornadus,,
|
|
||||||
232,Thundurus,,
|
|
||||||
233,Landorus,,
|
|
||||||
234,Enamorus,,
|
|
||||||
235,Dialga,,
|
|
||||||
236,Palkia,,
|
|
||||||
237,Giratina,,
|
|
||||||
238,Arceus,,
|
|
||||||
239,Phione,,
|
|
||||||
240,Manaphy,,
|
|
||||||
241,Shaymin,,
|
|
||||||
242,Darkrai,,
|
|
||||||
|
@@ -1,133 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Mankey,,
|
|
||||||
2,Primeape,,
|
|
||||||
3,Annihilape,,
|
|
||||||
4,Meowth,,
|
|
||||||
5,Persian,,
|
|
||||||
6,Perrserker,,
|
|
||||||
7,Farfetch’d,,
|
|
||||||
8,Sirfetch’d,,
|
|
||||||
9,Cubone,,
|
|
||||||
10,Marowak,,
|
|
||||||
11,Porygon,,
|
|
||||||
12,Porygon2,,
|
|
||||||
13,Porygon-Z,,
|
|
||||||
14,Capsakid,,
|
|
||||||
15,Scovillain,,
|
|
||||||
16,Tinkatink,,
|
|
||||||
17,Tinkatuff,,
|
|
||||||
18,Tinkaton,,
|
|
||||||
19,Cyclizar,,
|
|
||||||
20,Glimmet,,
|
|
||||||
21,Glimmora,,
|
|
||||||
22,Rotom,,
|
|
||||||
23,Greavard,,
|
|
||||||
24,Houndstone,,
|
|
||||||
25,Sandygast,,
|
|
||||||
26,Palossand,,
|
|
||||||
27,Kecleon,,
|
|
||||||
28,Flamigo,,
|
|
||||||
29,Cryogonal,,
|
|
||||||
30,Dondozo,,
|
|
||||||
31,Tatsugiri,,
|
|
||||||
32,Frigibax,,
|
|
||||||
33,Arctibax,,
|
|
||||||
34,Baxcalibur,,
|
|
||||||
35,Gimmighoul,,
|
|
||||||
36,Gholdengo,,
|
|
||||||
37,Qwilfish,,
|
|
||||||
38,Overqwil,,
|
|
||||||
39,Treecko,,
|
|
||||||
40,Grovyle,,
|
|
||||||
41,Sceptile,,
|
|
||||||
42,Torchic,,
|
|
||||||
43,Combusken,,
|
|
||||||
44,Blaziken,,
|
|
||||||
45,Mudkip,,
|
|
||||||
46,Marshtomp,,
|
|
||||||
47,Swampert,,
|
|
||||||
48,Feebas,,
|
|
||||||
49,Milotic,,
|
|
||||||
50,Chingling,,
|
|
||||||
51,Chimecho,,
|
|
||||||
52,Indeedee,,
|
|
||||||
53,Purrloin,,
|
|
||||||
54,Liepard,,
|
|
||||||
55,Munna,,
|
|
||||||
56,Musharna,,
|
|
||||||
57,Throh,,
|
|
||||||
58,Sawk,,
|
|
||||||
59,Yamask,,
|
|
||||||
60,Cofagrigus,,
|
|
||||||
61,Runerigus,,
|
|
||||||
62,Wimpod,,
|
|
||||||
63,Golisopod,,
|
|
||||||
64,Nickit,,
|
|
||||||
65,Thievul,,
|
|
||||||
66,Clobbopus,,
|
|
||||||
67,Grapploct,,
|
|
||||||
68,Mimikyu,,
|
|
||||||
69,Kleavor,,
|
|
||||||
70,Morpeko,,
|
|
||||||
71,Golett,,
|
|
||||||
72,Golurk,,
|
|
||||||
73,Rookidee,,
|
|
||||||
74,Corvisquire,,
|
|
||||||
75,Corviknight,,
|
|
||||||
76,Igglybuff,,
|
|
||||||
77,Jigglypuff,,
|
|
||||||
78,Wigglytuff,,
|
|
||||||
79,Fidough,,
|
|
||||||
80,Dachsbun,,
|
|
||||||
81,Starly,,
|
|
||||||
82,Staravia,,
|
|
||||||
83,Staraptor,,
|
|
||||||
84,Spoink,,
|
|
||||||
85,Grumpig,,
|
|
||||||
86,Squawkabilly,,
|
|
||||||
87,Crabrawler,,
|
|
||||||
88,Crabominable,,
|
|
||||||
89,Nacli,,
|
|
||||||
90,Naclstack,,
|
|
||||||
91,Garganacl,,
|
|
||||||
92,Gulpin,,
|
|
||||||
93,Swalot,,
|
|
||||||
94,Zubat,,
|
|
||||||
95,Golbat,,
|
|
||||||
96,Crobat,,
|
|
||||||
97,Charcadet,,
|
|
||||||
98,Armarouge,,
|
|
||||||
99,Ceruledge,,
|
|
||||||
100,Maschiff,,
|
|
||||||
101,Mabosstiff,,
|
|
||||||
102,Toxel,,
|
|
||||||
103,Toxtricity,,
|
|
||||||
104,Shroodle,,
|
|
||||||
105,Grafaiai,,
|
|
||||||
106,Zangoose,,
|
|
||||||
107,Seviper,,
|
|
||||||
108,Mime Jr.,,
|
|
||||||
109,Mr. Mime,,
|
|
||||||
110,Mr. Rime,,
|
|
||||||
111,Foongus,,
|
|
||||||
112,Amoonguss,,
|
|
||||||
113,Heatran,,
|
|
||||||
114,Volcanion,,
|
|
||||||
115,Cobalion,,
|
|
||||||
116,Terrakion,,
|
|
||||||
117,Virizion,,
|
|
||||||
118,Keldeo,,
|
|
||||||
119,Meloetta,,
|
|
||||||
120,Genesect,,
|
|
||||||
121,Hoopa,,
|
|
||||||
122,Marshadow,,
|
|
||||||
123,Meltan,,
|
|
||||||
124,Melmetal,,
|
|
||||||
125,Darkrai,,
|
|
||||||
126,Latias,,
|
|
||||||
127,Latios,,
|
|
||||||
128,Kyogre,,
|
|
||||||
129,Groudon,,
|
|
||||||
130,Rayquaza,,
|
|
||||||
131,Magearna,,
|
|
||||||
132,Zeraora,,
|
|
||||||
|
@@ -1,233 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Chikorita,,
|
|
||||||
2,Bayleef,,
|
|
||||||
3,Meganium,,
|
|
||||||
4,Tepig,,
|
|
||||||
5,Pignite,,
|
|
||||||
6,Emboar,,
|
|
||||||
7,Totodile,,
|
|
||||||
8,Croconaw,,
|
|
||||||
9,Feraligatr,,
|
|
||||||
10,Fletchling,,
|
|
||||||
11,Fletchinder,,
|
|
||||||
12,Talonflame,,
|
|
||||||
13,Bunnelby,,
|
|
||||||
14,Diggersby,,
|
|
||||||
15,Scatterbug,,
|
|
||||||
16,Spewpa,,
|
|
||||||
17,Vivillon,,
|
|
||||||
18,Weedle,,
|
|
||||||
19,Kakuna,,
|
|
||||||
20,Beedrill,,
|
|
||||||
21,Pidgey,,
|
|
||||||
22,Pidgeotto,,
|
|
||||||
23,Pidgeot,,
|
|
||||||
24,Mareep,,
|
|
||||||
25,Flaaffy,,
|
|
||||||
26,Ampharos,,
|
|
||||||
27,Patrat,,
|
|
||||||
28,Watchog,,
|
|
||||||
29,Budew,,
|
|
||||||
30,Roselia,,
|
|
||||||
31,Roserade,,
|
|
||||||
32,Magikarp,,
|
|
||||||
33,Gyarados,,
|
|
||||||
34,Binacle,,
|
|
||||||
35,Barbaracle,,
|
|
||||||
36,Staryu,,
|
|
||||||
37,Starmie,,
|
|
||||||
38,Flabébé,,
|
|
||||||
39,Floette,,
|
|
||||||
40,Florges,,
|
|
||||||
41,Skiddo,,
|
|
||||||
42,Gogoat,,
|
|
||||||
43,Espurr,,
|
|
||||||
44,Meowstic,,
|
|
||||||
45,Litleo,,
|
|
||||||
46,Pyroar,,
|
|
||||||
47,Pancham,,
|
|
||||||
48,Pangoro,,
|
|
||||||
49,Trubbish,,
|
|
||||||
50,Garbodor,,
|
|
||||||
51,Dedenne,,
|
|
||||||
52,Pichu,,
|
|
||||||
53,Pikachu,,
|
|
||||||
54,Raichu,,
|
|
||||||
55,Cleffa,,
|
|
||||||
56,Clefairy,,
|
|
||||||
57,Clefable,,
|
|
||||||
58,Spinarak,,
|
|
||||||
59,Ariados,,
|
|
||||||
60,Ekans,,
|
|
||||||
61,Arbok,,
|
|
||||||
62,Abra,,
|
|
||||||
63,Kadabra,,
|
|
||||||
64,Alakazam,,
|
|
||||||
65,Gastly,,
|
|
||||||
66,Haunter,,
|
|
||||||
67,Gengar,,
|
|
||||||
68,Venipede,,
|
|
||||||
69,Whirlipede,,
|
|
||||||
70,Scolipede,,
|
|
||||||
71,Honedge,,
|
|
||||||
72,Doublade,,
|
|
||||||
73,Aegislash,,
|
|
||||||
74,Bellsprout,,
|
|
||||||
75,Weepinbell,,
|
|
||||||
76,Victreebel,,
|
|
||||||
77,Pansage,,
|
|
||||||
78,Simisage,,
|
|
||||||
79,Pansear,,
|
|
||||||
80,Simisear,,
|
|
||||||
81,Panpour,,
|
|
||||||
82,Simipour,,
|
|
||||||
83,Meditite,,
|
|
||||||
84,Medicham,,
|
|
||||||
85,Electrike,,
|
|
||||||
86,Manectric,,
|
|
||||||
87,Ralts,,
|
|
||||||
88,Kirlia,,
|
|
||||||
89,Gardevoir,,
|
|
||||||
90,Gallade,,
|
|
||||||
91,Houndour,,
|
|
||||||
92,Houndoom,,
|
|
||||||
93,Swablu,,
|
|
||||||
94,Altaria,,
|
|
||||||
95,Audino,,
|
|
||||||
96,Spritzee,,
|
|
||||||
97,Aromatisse,,
|
|
||||||
98,Swirlix,,
|
|
||||||
99,Slurpuff,,
|
|
||||||
100,Eevee,,
|
|
||||||
101,Vaporeon,,
|
|
||||||
102,Jolteon,,
|
|
||||||
103,Flareon,,
|
|
||||||
104,Espeon,,
|
|
||||||
105,Umbreon,,
|
|
||||||
106,Leafeon,,
|
|
||||||
107,Glaceon,,
|
|
||||||
108,Sylveon,,
|
|
||||||
109,Buneary,,
|
|
||||||
110,Lopunny,,
|
|
||||||
111,Shuppet,,
|
|
||||||
112,Banette,,
|
|
||||||
113,Vanillite,,
|
|
||||||
114,Vanillish,,
|
|
||||||
115,Vanilluxe,,
|
|
||||||
116,Numel,,
|
|
||||||
117,Camerupt,,
|
|
||||||
118,Hippopotas,,
|
|
||||||
119,Hippowdon,,
|
|
||||||
120,Drilbur,,
|
|
||||||
121,Excadrill,,
|
|
||||||
122,Sandile,,
|
|
||||||
123,Krokorok,,
|
|
||||||
124,Krookodile,,
|
|
||||||
125,Machop,,
|
|
||||||
126,Machoke,,
|
|
||||||
127,Machamp,,
|
|
||||||
128,Gible,,
|
|
||||||
129,Gabite,,
|
|
||||||
130,Garchomp,,
|
|
||||||
131,Carbink,,
|
|
||||||
132,Sableye,,
|
|
||||||
133,Mawile,,
|
|
||||||
134,Absol,,
|
|
||||||
135,Riolu,,
|
|
||||||
136,Lucario,,
|
|
||||||
137,Slowpoke,,
|
|
||||||
138,Slowbro,,
|
|
||||||
139,Slowking,,
|
|
||||||
140,Carvanha,,
|
|
||||||
141,Sharpedo,,
|
|
||||||
142,Tynamo,,
|
|
||||||
143,Eelektrik,,
|
|
||||||
144,Eelektross,,
|
|
||||||
145,Dratini,,
|
|
||||||
146,Dragonair,,
|
|
||||||
147,Dragonite,,
|
|
||||||
148,Bulbasaur,,
|
|
||||||
149,Ivysaur,,
|
|
||||||
150,Venusaur,,
|
|
||||||
151,Charmander,,
|
|
||||||
152,Charmeleon,,
|
|
||||||
153,Charizard,,
|
|
||||||
154,Squirtle,,
|
|
||||||
155,Wartortle,,
|
|
||||||
156,Blastoise,,
|
|
||||||
157,Stunfisk,,
|
|
||||||
158,Furfrou,,
|
|
||||||
159,Inkay,,
|
|
||||||
160,Malamar,,
|
|
||||||
161,Skrelp,,
|
|
||||||
162,Dragalge,,
|
|
||||||
163,Clauncher,,
|
|
||||||
164,Clawitzer,,
|
|
||||||
165,Goomy,,
|
|
||||||
166,Sliggoo,,
|
|
||||||
167,Goodra,,
|
|
||||||
168,Delibird,,
|
|
||||||
169,Snorunt,,
|
|
||||||
170,Glalie,,
|
|
||||||
171,Froslass,,
|
|
||||||
172,Snover,,
|
|
||||||
173,Abomasnow,,
|
|
||||||
174,Bergmite,,
|
|
||||||
175,Avalugg,,
|
|
||||||
176,Scyther,,
|
|
||||||
177,Scizor,,
|
|
||||||
178,Pinsir,,
|
|
||||||
179,Heracross,,
|
|
||||||
180,Emolga,,
|
|
||||||
181,Hawlucha,,
|
|
||||||
182,Phantump,,
|
|
||||||
183,Trevenant,,
|
|
||||||
184,Scraggy,,
|
|
||||||
185,Scrafty,,
|
|
||||||
186,Noibat,,
|
|
||||||
187,Noivern,,
|
|
||||||
188,Klefki,,
|
|
||||||
189,Litwick,,
|
|
||||||
190,Lampent,,
|
|
||||||
191,Chandelure,,
|
|
||||||
192,Aerodactyl,,
|
|
||||||
193,Tyrunt,,
|
|
||||||
194,Tyrantrum,,
|
|
||||||
195,Amaura,,
|
|
||||||
196,Aurorus,,
|
|
||||||
197,Onix,,
|
|
||||||
198,Steelix,,
|
|
||||||
199,Aron,,
|
|
||||||
200,Lairon,,
|
|
||||||
201,Aggron,,
|
|
||||||
202,Helioptile,,
|
|
||||||
203,Heliolisk,,
|
|
||||||
204,Pumpkaboo,,
|
|
||||||
205,Gourgeist,,
|
|
||||||
206,Larvitar,,
|
|
||||||
207,Pupitar,,
|
|
||||||
208,Tyranitar,,
|
|
||||||
209,Froakie,,
|
|
||||||
210,Frogadier,,
|
|
||||||
211,Greninja,,
|
|
||||||
212,Falinks,,
|
|
||||||
213,Chespin,,
|
|
||||||
214,Quilladin,,
|
|
||||||
215,Chesnaught,,
|
|
||||||
216,Skarmory,,
|
|
||||||
217,Fennekin,,
|
|
||||||
218,Braixen,,
|
|
||||||
219,Delphox,,
|
|
||||||
220,Bagon,,
|
|
||||||
221,Shelgon,,
|
|
||||||
222,Salamence,,
|
|
||||||
223,Kangaskhan,,
|
|
||||||
224,Drampa,,
|
|
||||||
225,Beldum,,
|
|
||||||
226,Metang,,
|
|
||||||
227,Metagross,,
|
|
||||||
228,Xerneas,,
|
|
||||||
229,Yveltal,,
|
|
||||||
230,Zygarde,,
|
|
||||||
231,Diancie,,
|
|
||||||
232,Mewtwo,,
|
|
||||||
|
@@ -1,154 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Bulbasaur,,
|
|
||||||
2,Ivysaur,,
|
|
||||||
3,Venusaur,,
|
|
||||||
4,Charmander,,
|
|
||||||
5,Charmeleon,,
|
|
||||||
6,Charizard,,
|
|
||||||
7,Squirtle,,
|
|
||||||
8,Wartortle,,
|
|
||||||
9,Blastoise,,
|
|
||||||
10,Caterpie,,
|
|
||||||
11,Metapod,,
|
|
||||||
12,Butterfree,,
|
|
||||||
13,Weedle,,
|
|
||||||
14,Kakuna,,
|
|
||||||
15,Beedrill,,
|
|
||||||
16,Pidgey,,
|
|
||||||
17,Pidgeotto,,
|
|
||||||
18,Pidgeot,,
|
|
||||||
19,Rattata,,
|
|
||||||
20,Raticate,,
|
|
||||||
21,Spearow,,
|
|
||||||
22,Fearow,,
|
|
||||||
23,Ekans,,
|
|
||||||
24,Arbok,,
|
|
||||||
25,Pikachu,,
|
|
||||||
26,Raichu,,
|
|
||||||
27,Sandshrew,,
|
|
||||||
28,Sandslash,,
|
|
||||||
29,Nidoran♀,,
|
|
||||||
30,Nidorina,,
|
|
||||||
31,Nidoqueen,,
|
|
||||||
32,Nidoran♂,,
|
|
||||||
33,Nidorino,,
|
|
||||||
34,Nidoking,,
|
|
||||||
35,Clefairy,,
|
|
||||||
36,Clefable,,
|
|
||||||
37,Vulpix,,
|
|
||||||
38,Ninetales,,
|
|
||||||
39,Jigglypuff,,
|
|
||||||
40,Wigglytuff,,
|
|
||||||
41,Zubat,,
|
|
||||||
42,Golbat,,
|
|
||||||
43,Oddish,,
|
|
||||||
44,Gloom,,
|
|
||||||
45,Vileplume,,
|
|
||||||
46,Paras,,
|
|
||||||
47,Parasect,,
|
|
||||||
48,Venonat,,
|
|
||||||
49,Venomoth,,
|
|
||||||
50,Diglett,,
|
|
||||||
51,Dugtrio,,
|
|
||||||
52,Meowth,,
|
|
||||||
53,Persian,,
|
|
||||||
54,Psyduck,,
|
|
||||||
55,Golduck,,
|
|
||||||
56,Mankey,,
|
|
||||||
57,Primeape,,
|
|
||||||
58,Growlithe,,
|
|
||||||
59,Arcanine,,
|
|
||||||
60,Poliwag,,
|
|
||||||
61,Poliwhirl,,
|
|
||||||
62,Poliwrath,,
|
|
||||||
63,Abra,,
|
|
||||||
64,Kadabra,,
|
|
||||||
65,Alakazam,,
|
|
||||||
66,Machop,,
|
|
||||||
67,Machoke,,
|
|
||||||
68,Machamp,,
|
|
||||||
69,Bellsprout,,
|
|
||||||
70,Weepinbell,,
|
|
||||||
71,Victreebel,,
|
|
||||||
72,Tentacool,,
|
|
||||||
73,Tentacruel,,
|
|
||||||
74,Geodude,,
|
|
||||||
75,Graveler,,
|
|
||||||
76,Golem,,
|
|
||||||
77,Ponyta,,
|
|
||||||
78,Rapidash,,
|
|
||||||
79,Slowpoke,,
|
|
||||||
80,Slowbro,,
|
|
||||||
81,Magnemite,,
|
|
||||||
82,Magneton,,
|
|
||||||
83,Farfetch’d,,
|
|
||||||
84,Doduo,,
|
|
||||||
85,Dodrio,,
|
|
||||||
86,Seel,,
|
|
||||||
87,Dewgong,,
|
|
||||||
88,Grimer,,
|
|
||||||
89,Muk,,
|
|
||||||
90,Shellder,,
|
|
||||||
91,Cloyster,,
|
|
||||||
92,Gastly,,
|
|
||||||
93,Haunter,,
|
|
||||||
94,Gengar,,
|
|
||||||
95,Onix,,
|
|
||||||
96,Drowzee,,
|
|
||||||
97,Hypno,,
|
|
||||||
98,Krabby,,
|
|
||||||
99,Kingler,,
|
|
||||||
100,Voltorb,,
|
|
||||||
101,Electrode,,
|
|
||||||
102,Exeggcute,,
|
|
||||||
103,Exeggutor,,
|
|
||||||
104,Cubone,,
|
|
||||||
105,Marowak,,
|
|
||||||
106,Hitmonlee,,
|
|
||||||
107,Hitmonchan,,
|
|
||||||
108,Lickitung,,
|
|
||||||
109,Koffing,,
|
|
||||||
110,Weezing,,
|
|
||||||
111,Rhyhorn,,
|
|
||||||
112,Rhydon,,
|
|
||||||
113,Chansey,,
|
|
||||||
114,Tangela,,
|
|
||||||
115,Kangaskhan,,
|
|
||||||
116,Horsea,,
|
|
||||||
117,Seadra,,
|
|
||||||
118,Goldeen,,
|
|
||||||
119,Seaking,,
|
|
||||||
120,Staryu,,
|
|
||||||
121,Starmie,,
|
|
||||||
122,Mr. Mime,,
|
|
||||||
123,Scyther,,
|
|
||||||
124,Jynx,,
|
|
||||||
125,Electabuzz,,
|
|
||||||
126,Magmar,,
|
|
||||||
127,Pinsir,,
|
|
||||||
128,Tauros,,
|
|
||||||
129,Magikarp,,
|
|
||||||
130,Gyarados,,
|
|
||||||
131,Lapras,,
|
|
||||||
132,Ditto,,
|
|
||||||
133,Eevee,,
|
|
||||||
134,Vaporeon,,
|
|
||||||
135,Jolteon,,
|
|
||||||
136,Flareon,,
|
|
||||||
137,Porygon,,
|
|
||||||
138,Omanyte,,
|
|
||||||
139,Omastar,,
|
|
||||||
140,Kabuto,,
|
|
||||||
141,Kabutops,,
|
|
||||||
142,Aerodactyl,,
|
|
||||||
143,Snorlax,,
|
|
||||||
144,Articuno,,
|
|
||||||
145,Zapdos,,
|
|
||||||
146,Moltres,,
|
|
||||||
147,Dratini,,
|
|
||||||
148,Dragonair,,
|
|
||||||
149,Dragonite,,
|
|
||||||
150,Mewtwo,,
|
|
||||||
151,Mew,,
|
|
||||||
152,Meltan,,
|
|
||||||
153,Melmetal,,
|
|
||||||
|
@@ -1,212 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Treecko,,
|
|
||||||
2,Grovyle,,
|
|
||||||
3,Sceptile,,
|
|
||||||
4,Torchic,,
|
|
||||||
5,Combusken,,
|
|
||||||
6,Blaziken,,
|
|
||||||
7,Mudkip,,
|
|
||||||
8,Marshtomp,,
|
|
||||||
9,Swampert,,
|
|
||||||
10,Poochyena,,
|
|
||||||
11,Mightyena,,
|
|
||||||
12,Zigzagoon,,
|
|
||||||
13,Linoone,,
|
|
||||||
14,Wurmple,,
|
|
||||||
15,Silcoon,,
|
|
||||||
16,Beautifly,,
|
|
||||||
17,Cascoon,,
|
|
||||||
18,Dustox,,
|
|
||||||
19,Lotad,,
|
|
||||||
20,Lombre,,
|
|
||||||
21,Ludicolo,,
|
|
||||||
22,Seedot,,
|
|
||||||
23,Nuzleaf,,
|
|
||||||
24,Shiftry,,
|
|
||||||
25,Taillow,,
|
|
||||||
26,Swellow,,
|
|
||||||
27,Wingull,,
|
|
||||||
28,Pelipper,,
|
|
||||||
29,Ralts,,
|
|
||||||
30,Kirlia,,
|
|
||||||
31,Gardevoir,,
|
|
||||||
32,Gallade,,
|
|
||||||
33,Surskit,,
|
|
||||||
34,Masquerain,,
|
|
||||||
35,Shroomish,,
|
|
||||||
36,Breloom,,
|
|
||||||
37,Slakoth,,
|
|
||||||
38,Vigoroth,,
|
|
||||||
39,Slaking,,
|
|
||||||
40,Abra,,
|
|
||||||
41,Kadabra,,
|
|
||||||
42,Alakazam,,
|
|
||||||
43,Nincada,,
|
|
||||||
44,Ninjask,,
|
|
||||||
45,Shedinja,,
|
|
||||||
46,Whismur,,
|
|
||||||
47,Loudred,,
|
|
||||||
48,Exploud,,
|
|
||||||
49,Makuhita,,
|
|
||||||
50,Hariyama,,
|
|
||||||
51,Goldeen,,
|
|
||||||
52,Seaking,,
|
|
||||||
53,Magikarp,,
|
|
||||||
54,Gyarados,,
|
|
||||||
55,Azurill,,
|
|
||||||
56,Marill,,
|
|
||||||
57,Azumarill,,
|
|
||||||
58,Geodude,,
|
|
||||||
59,Graveler,,
|
|
||||||
60,Golem,,
|
|
||||||
61,Nosepass,,
|
|
||||||
62,Probopass,,
|
|
||||||
63,Skitty,,
|
|
||||||
64,Delcatty,,
|
|
||||||
65,Zubat,,
|
|
||||||
66,Golbat,,
|
|
||||||
67,Crobat,,
|
|
||||||
68,Tentacool,,
|
|
||||||
69,Tentacruel,,
|
|
||||||
70,Sableye,,
|
|
||||||
71,Mawile,,
|
|
||||||
72,Aron,,
|
|
||||||
73,Lairon,,
|
|
||||||
74,Aggron,,
|
|
||||||
75,Machop,,
|
|
||||||
76,Machoke,,
|
|
||||||
77,Machamp,,
|
|
||||||
78,Meditite,,
|
|
||||||
79,Medicham,,
|
|
||||||
80,Electrike,,
|
|
||||||
81,Manectric,,
|
|
||||||
82,Plusle,,
|
|
||||||
83,Minun,,
|
|
||||||
84,Magnemite,,
|
|
||||||
85,Magneton,,
|
|
||||||
86,Magnezone,,
|
|
||||||
87,Voltorb,,
|
|
||||||
88,Electrode,,
|
|
||||||
89,Volbeat,,
|
|
||||||
90,Illumise,,
|
|
||||||
91,Oddish,,
|
|
||||||
92,Gloom,,
|
|
||||||
93,Vileplume,,
|
|
||||||
94,Bellossom,,
|
|
||||||
95,Doduo,,
|
|
||||||
96,Dodrio,,
|
|
||||||
97,Budew,,
|
|
||||||
98,Roselia,,
|
|
||||||
99,Roserade,,
|
|
||||||
100,Gulpin,,
|
|
||||||
101,Swalot,,
|
|
||||||
102,Carvanha,,
|
|
||||||
103,Sharpedo,,
|
|
||||||
104,Wailmer,,
|
|
||||||
105,Wailord,,
|
|
||||||
106,Numel,,
|
|
||||||
107,Camerupt,,
|
|
||||||
108,Slugma,,
|
|
||||||
109,Magcargo,,
|
|
||||||
110,Torkoal,,
|
|
||||||
111,Grimer,,
|
|
||||||
112,Muk,,
|
|
||||||
113,Koffing,,
|
|
||||||
114,Weezing,,
|
|
||||||
115,Spoink,,
|
|
||||||
116,Grumpig,,
|
|
||||||
117,Sandshrew,,
|
|
||||||
118,Sandslash,,
|
|
||||||
119,Spinda,,
|
|
||||||
120,Skarmory,,
|
|
||||||
121,Trapinch,,
|
|
||||||
122,Vibrava,,
|
|
||||||
123,Flygon,,
|
|
||||||
124,Cacnea,,
|
|
||||||
125,Cacturne,,
|
|
||||||
126,Swablu,,
|
|
||||||
127,Altaria,,
|
|
||||||
128,Zangoose,,
|
|
||||||
129,Seviper,,
|
|
||||||
130,Lunatone,,
|
|
||||||
131,Solrock,,
|
|
||||||
132,Barboach,,
|
|
||||||
133,Whiscash,,
|
|
||||||
134,Corphish,,
|
|
||||||
135,Crawdaunt,,
|
|
||||||
136,Baltoy,,
|
|
||||||
137,Claydol,,
|
|
||||||
138,Lileep,,
|
|
||||||
139,Cradily,,
|
|
||||||
140,Anorith,,
|
|
||||||
141,Armaldo,,
|
|
||||||
142,Igglybuff,,
|
|
||||||
143,Jigglypuff,,
|
|
||||||
144,Wigglytuff,,
|
|
||||||
145,Feebas,,
|
|
||||||
146,Milotic,,
|
|
||||||
147,Castform,,
|
|
||||||
148,Staryu,,
|
|
||||||
149,Starmie,,
|
|
||||||
150,Kecleon,,
|
|
||||||
151,Shuppet,,
|
|
||||||
152,Banette,,
|
|
||||||
153,Duskull,,
|
|
||||||
154,Dusclops,,
|
|
||||||
155,Dusknoir,,
|
|
||||||
156,Tropius,,
|
|
||||||
157,Chingling,,
|
|
||||||
158,Chimecho,,
|
|
||||||
159,Absol,,
|
|
||||||
160,Vulpix,,
|
|
||||||
161,Ninetales,,
|
|
||||||
162,Pichu,,
|
|
||||||
163,Pikachu,,
|
|
||||||
164,Raichu,,
|
|
||||||
165,Psyduck,,
|
|
||||||
166,Golduck,,
|
|
||||||
167,Wynaut,,
|
|
||||||
168,Wobbuffet,,
|
|
||||||
169,Natu,,
|
|
||||||
170,Xatu,,
|
|
||||||
171,Girafarig,,
|
|
||||||
172,Phanpy,,
|
|
||||||
173,Donphan,,
|
|
||||||
174,Pinsir,,
|
|
||||||
175,Heracross,,
|
|
||||||
176,Rhyhorn,,
|
|
||||||
177,Rhydon,,
|
|
||||||
178,Rhyperior,,
|
|
||||||
179,Snorunt,,
|
|
||||||
180,Glalie,,
|
|
||||||
181,Froslass,,
|
|
||||||
182,Spheal,,
|
|
||||||
183,Sealeo,,
|
|
||||||
184,Walrein,,
|
|
||||||
185,Clamperl,,
|
|
||||||
186,Huntail,,
|
|
||||||
187,Gorebyss,,
|
|
||||||
188,Relicanth,,
|
|
||||||
189,Corsola,,
|
|
||||||
190,Chinchou,,
|
|
||||||
191,Lanturn,,
|
|
||||||
192,Luvdisc,,
|
|
||||||
193,Horsea,,
|
|
||||||
194,Seadra,,
|
|
||||||
195,Kingdra,,
|
|
||||||
196,Bagon,,
|
|
||||||
197,Shelgon,,
|
|
||||||
198,Salamence,,
|
|
||||||
199,Beldum,,
|
|
||||||
200,Metang,,
|
|
||||||
201,Metagross,,
|
|
||||||
202,Regirock,,
|
|
||||||
203,Regice,,
|
|
||||||
204,Registeel,,
|
|
||||||
205,Latias,,
|
|
||||||
206,Latios,,
|
|
||||||
207,Kyogre,,
|
|
||||||
208,Groudon,,
|
|
||||||
209,Rayquaza,,
|
|
||||||
210,Jirachi,,
|
|
||||||
211,Deoxys,,
|
|
||||||
|
@@ -1,211 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Turtwig,,
|
|
||||||
2,Grotle,,
|
|
||||||
3,Torterra,,
|
|
||||||
4,Chimchar,,
|
|
||||||
5,Monferno,,
|
|
||||||
6,Infernape,,
|
|
||||||
7,Piplup,,
|
|
||||||
8,Prinplup,,
|
|
||||||
9,Empoleon,,
|
|
||||||
10,Starly,,
|
|
||||||
11,Staravia,,
|
|
||||||
12,Staraptor,,
|
|
||||||
13,Bidoof,,
|
|
||||||
14,Bibarel,,
|
|
||||||
15,Kricketot,,
|
|
||||||
16,Kricketune,,
|
|
||||||
17,Shinx,,
|
|
||||||
18,Luxio,,
|
|
||||||
19,Luxray,,
|
|
||||||
20,Abra,,
|
|
||||||
21,Kadabra,,
|
|
||||||
22,Alakazam,,
|
|
||||||
23,Magikarp,,
|
|
||||||
24,Gyarados,,
|
|
||||||
25,Budew,,
|
|
||||||
26,Roselia,,
|
|
||||||
27,Roserade,,
|
|
||||||
28,Zubat,,
|
|
||||||
29,Golbat,,
|
|
||||||
30,Crobat,,
|
|
||||||
31,Geodude,,
|
|
||||||
32,Graveler,,
|
|
||||||
33,Golem,,
|
|
||||||
34,Onix,,
|
|
||||||
35,Steelix,,
|
|
||||||
36,Cranidos,,
|
|
||||||
37,Rampardos,,
|
|
||||||
38,Shieldon,,
|
|
||||||
39,Bastiodon,,
|
|
||||||
40,Machop,,
|
|
||||||
41,Machoke,,
|
|
||||||
42,Machamp,,
|
|
||||||
43,Psyduck,,
|
|
||||||
44,Golduck,,
|
|
||||||
45,Burmy,,
|
|
||||||
46,Wormadam,,
|
|
||||||
47,Mothim,,
|
|
||||||
48,Wurmple,,
|
|
||||||
49,Silcoon,,
|
|
||||||
50,Beautifly,,
|
|
||||||
51,Cascoon,,
|
|
||||||
52,Dustox,,
|
|
||||||
53,Combee,,
|
|
||||||
54,Vespiquen,,
|
|
||||||
55,Pachirisu,,
|
|
||||||
56,Buizel,,
|
|
||||||
57,Floatzel,,
|
|
||||||
58,Cherubi,,
|
|
||||||
59,Cherrim,,
|
|
||||||
60,Shellos,,
|
|
||||||
61,Gastrodon,,
|
|
||||||
62,Heracross,,
|
|
||||||
63,Aipom,,
|
|
||||||
64,Ambipom,,
|
|
||||||
65,Drifloon,,
|
|
||||||
66,Drifblim,,
|
|
||||||
67,Buneary,,
|
|
||||||
68,Lopunny,,
|
|
||||||
69,Gastly,,
|
|
||||||
70,Haunter,,
|
|
||||||
71,Gengar,,
|
|
||||||
72,Misdreavus,,
|
|
||||||
73,Mismagius,,
|
|
||||||
74,Murkrow,,
|
|
||||||
75,Honchkrow,,
|
|
||||||
76,Glameow,,
|
|
||||||
77,Purugly,,
|
|
||||||
78,Goldeen,,
|
|
||||||
79,Seaking,,
|
|
||||||
80,Barboach,,
|
|
||||||
81,Whiscash,,
|
|
||||||
82,Chingling,,
|
|
||||||
83,Chimecho,,
|
|
||||||
84,Stunky,,
|
|
||||||
85,Skuntank,,
|
|
||||||
86,Meditite,,
|
|
||||||
87,Medicham,,
|
|
||||||
88,Bronzor,,
|
|
||||||
89,Bronzong,,
|
|
||||||
90,Ponyta,,
|
|
||||||
91,Rapidash,,
|
|
||||||
92,Bonsly,,
|
|
||||||
93,Sudowoodo,,
|
|
||||||
94,Mime Jr.,,
|
|
||||||
95,Mr. Mime,,
|
|
||||||
96,Happiny,,
|
|
||||||
97,Chansey,,
|
|
||||||
98,Blissey,,
|
|
||||||
99,Cleffa,,
|
|
||||||
100,Clefairy,,
|
|
||||||
101,Clefable,,
|
|
||||||
102,Chatot,,
|
|
||||||
103,Pichu,,
|
|
||||||
104,Pikachu,,
|
|
||||||
105,Raichu,,
|
|
||||||
106,Hoothoot,,
|
|
||||||
107,Noctowl,,
|
|
||||||
108,Spiritomb,,
|
|
||||||
109,Gible,,
|
|
||||||
110,Gabite,,
|
|
||||||
111,Garchomp,,
|
|
||||||
112,Munchlax,,
|
|
||||||
113,Snorlax,,
|
|
||||||
114,Unown,,
|
|
||||||
115,Riolu,,
|
|
||||||
116,Lucario,,
|
|
||||||
117,Wooper,,
|
|
||||||
118,Quagsire,,
|
|
||||||
119,Wingull,,
|
|
||||||
120,Pelipper,,
|
|
||||||
121,Girafarig,,
|
|
||||||
122,Hippopotas,,
|
|
||||||
123,Hippowdon,,
|
|
||||||
124,Azurill,,
|
|
||||||
125,Marill,,
|
|
||||||
126,Azumarill,,
|
|
||||||
127,Skorupi,,
|
|
||||||
128,Drapion,,
|
|
||||||
129,Croagunk,,
|
|
||||||
130,Toxicroak,,
|
|
||||||
131,Carnivine,,
|
|
||||||
132,Remoraid,,
|
|
||||||
133,Octillery,,
|
|
||||||
134,Finneon,,
|
|
||||||
135,Lumineon,,
|
|
||||||
136,Tentacool,,
|
|
||||||
137,Tentacruel,,
|
|
||||||
138,Feebas,,
|
|
||||||
139,Milotic,,
|
|
||||||
140,Mantyke,,
|
|
||||||
141,Mantine,,
|
|
||||||
142,Snover,,
|
|
||||||
143,Abomasnow,,
|
|
||||||
144,Sneasel,,
|
|
||||||
145,Weavile,,
|
|
||||||
146,Uxie,,
|
|
||||||
147,Mesprit,,
|
|
||||||
148,Azelf,,
|
|
||||||
149,Dialga,,
|
|
||||||
150,Palkia,,
|
|
||||||
151,Manaphy,,
|
|
||||||
152,Rotom,,
|
|
||||||
153,Gligar,,
|
|
||||||
154,Gliscor,,
|
|
||||||
155,Nosepass,,
|
|
||||||
156,Probopass,,
|
|
||||||
157,Ralts,,
|
|
||||||
158,Kirlia,,
|
|
||||||
159,Gardevoir,,
|
|
||||||
160,Gallade,,
|
|
||||||
161,Lickitung,,
|
|
||||||
162,Lickilicky,,
|
|
||||||
163,Eevee,,
|
|
||||||
164,Vaporeon,,
|
|
||||||
165,Jolteon,,
|
|
||||||
166,Flareon,,
|
|
||||||
167,Espeon,,
|
|
||||||
168,Umbreon,,
|
|
||||||
169,Leafeon,,
|
|
||||||
170,Glaceon,,
|
|
||||||
171,Swablu,,
|
|
||||||
172,Altaria,,
|
|
||||||
173,Togepi,,
|
|
||||||
174,Togetic,,
|
|
||||||
175,Togekiss,,
|
|
||||||
176,Houndour,,
|
|
||||||
177,Houndoom,,
|
|
||||||
178,Magnemite,,
|
|
||||||
179,Magneton,,
|
|
||||||
180,Magnezone,,
|
|
||||||
181,Tangela,,
|
|
||||||
182,Tangrowth,,
|
|
||||||
183,Yanma,,
|
|
||||||
184,Yanmega,,
|
|
||||||
185,Tropius,,
|
|
||||||
186,Rhyhorn,,
|
|
||||||
187,Rhydon,,
|
|
||||||
188,Rhyperior,,
|
|
||||||
189,Duskull,,
|
|
||||||
190,Dusclops,,
|
|
||||||
191,Dusknoir,,
|
|
||||||
192,Porygon,,
|
|
||||||
193,Porygon2,,
|
|
||||||
194,Porygon-Z,,
|
|
||||||
195,Scyther,,
|
|
||||||
196,Scizor,,
|
|
||||||
197,Elekid,,
|
|
||||||
198,Electabuzz,,
|
|
||||||
199,Electivire,,
|
|
||||||
200,Magby,,
|
|
||||||
201,Magmar,,
|
|
||||||
202,Magmortar,,
|
|
||||||
203,Swinub,,
|
|
||||||
204,Piloswine,,
|
|
||||||
205,Mamoswine,,
|
|
||||||
206,Snorunt,,
|
|
||||||
207,Glalie,,
|
|
||||||
208,Froslass,,
|
|
||||||
209,Absol,,
|
|
||||||
210,Giratina,,
|
|
||||||
|
@@ -1,152 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Bulbasaur,,
|
|
||||||
2,Ivysaur,,
|
|
||||||
3,Venusaur,,
|
|
||||||
4,Charmander,,
|
|
||||||
5,Charmeleon,,
|
|
||||||
6,Charizard,,
|
|
||||||
7,Squirtle,,
|
|
||||||
8,Wartortle,,
|
|
||||||
9,Blastoise,,
|
|
||||||
10,Caterpie,,
|
|
||||||
11,Metapod,,
|
|
||||||
12,Butterfree,,
|
|
||||||
13,Weedle,,
|
|
||||||
14,Kakuna,,
|
|
||||||
15,Beedrill,,
|
|
||||||
16,Pidgey,,
|
|
||||||
17,Pidgeotto,,
|
|
||||||
18,Pidgeot,,
|
|
||||||
19,Rattata,,
|
|
||||||
20,Raticate,,
|
|
||||||
21,Spearow,,
|
|
||||||
22,Fearow,,
|
|
||||||
23,Ekans,,
|
|
||||||
24,Arbok,,
|
|
||||||
25,Pikachu,,
|
|
||||||
26,Raichu,,
|
|
||||||
27,Sandshrew,,
|
|
||||||
28,Sandslash,,
|
|
||||||
29,Nidoran♀,,
|
|
||||||
30,Nidorina,,
|
|
||||||
31,Nidoqueen,,
|
|
||||||
32,Nidoran♂,,
|
|
||||||
33,Nidorino,,
|
|
||||||
34,Nidoking,,
|
|
||||||
35,Clefairy,,
|
|
||||||
36,Clefable,,
|
|
||||||
37,Vulpix,,
|
|
||||||
38,Ninetales,,
|
|
||||||
39,Jigglypuff,,
|
|
||||||
40,Wigglytuff,,
|
|
||||||
41,Zubat,,
|
|
||||||
42,Golbat,,
|
|
||||||
43,Oddish,,
|
|
||||||
44,Gloom,,
|
|
||||||
45,Vileplume,,
|
|
||||||
46,Paras,,
|
|
||||||
47,Parasect,,
|
|
||||||
48,Venonat,,
|
|
||||||
49,Venomoth,,
|
|
||||||
50,Diglett,,
|
|
||||||
51,Dugtrio,,
|
|
||||||
52,Meowth,,
|
|
||||||
53,Persian,,
|
|
||||||
54,Psyduck,,
|
|
||||||
55,Golduck,,
|
|
||||||
56,Mankey,,
|
|
||||||
57,Primeape,,
|
|
||||||
58,Growlithe,,
|
|
||||||
59,Arcanine,,
|
|
||||||
60,Poliwag,,
|
|
||||||
61,Poliwhirl,,
|
|
||||||
62,Poliwrath,,
|
|
||||||
63,Abra,,
|
|
||||||
64,Kadabra,,
|
|
||||||
65,Alakazam,,
|
|
||||||
66,Machop,,
|
|
||||||
67,Machoke,,
|
|
||||||
68,Machamp,,
|
|
||||||
69,Bellsprout,,
|
|
||||||
70,Weepinbell,,
|
|
||||||
71,Victreebel,,
|
|
||||||
72,Tentacool,,
|
|
||||||
73,Tentacruel,,
|
|
||||||
74,Geodude,,
|
|
||||||
75,Graveler,,
|
|
||||||
76,Golem,,
|
|
||||||
77,Ponyta,,
|
|
||||||
78,Rapidash,,
|
|
||||||
79,Slowpoke,,
|
|
||||||
80,Slowbro,,
|
|
||||||
81,Magnemite,,
|
|
||||||
82,Magneton,,
|
|
||||||
83,Farfetch’d,,
|
|
||||||
84,Doduo,,
|
|
||||||
85,Dodrio,,
|
|
||||||
86,Seel,,
|
|
||||||
87,Dewgong,,
|
|
||||||
88,Grimer,,
|
|
||||||
89,Muk,,
|
|
||||||
90,Shellder,,
|
|
||||||
91,Cloyster,,
|
|
||||||
92,Gastly,,
|
|
||||||
93,Haunter,,
|
|
||||||
94,Gengar,,
|
|
||||||
95,Onix,,
|
|
||||||
96,Drowzee,,
|
|
||||||
97,Hypno,,
|
|
||||||
98,Krabby,,
|
|
||||||
99,Kingler,,
|
|
||||||
100,Voltorb,,
|
|
||||||
101,Electrode,,
|
|
||||||
102,Exeggcute,,
|
|
||||||
103,Exeggutor,,
|
|
||||||
104,Cubone,,
|
|
||||||
105,Marowak,,
|
|
||||||
106,Hitmonlee,,
|
|
||||||
107,Hitmonchan,,
|
|
||||||
108,Lickitung,,
|
|
||||||
109,Koffing,,
|
|
||||||
110,Weezing,,
|
|
||||||
111,Rhyhorn,,
|
|
||||||
112,Rhydon,,
|
|
||||||
113,Chansey,,
|
|
||||||
114,Tangela,,
|
|
||||||
115,Kangaskhan,,
|
|
||||||
116,Horsea,,
|
|
||||||
117,Seadra,,
|
|
||||||
118,Goldeen,,
|
|
||||||
119,Seaking,,
|
|
||||||
120,Staryu,,
|
|
||||||
121,Starmie,,
|
|
||||||
122,Mr. Mime,,
|
|
||||||
123,Scyther,,
|
|
||||||
124,Jynx,,
|
|
||||||
125,Electabuzz,,
|
|
||||||
126,Magmar,,
|
|
||||||
127,Pinsir,,
|
|
||||||
128,Tauros,,
|
|
||||||
129,Magikarp,,
|
|
||||||
130,Gyarados,,
|
|
||||||
131,Lapras,,
|
|
||||||
132,Ditto,,
|
|
||||||
133,Eevee,,
|
|
||||||
134,Vaporeon,,
|
|
||||||
135,Jolteon,,
|
|
||||||
136,Flareon,,
|
|
||||||
137,Porygon,,
|
|
||||||
138,Omanyte,,
|
|
||||||
139,Omastar,,
|
|
||||||
140,Kabuto,,
|
|
||||||
141,Kabutops,,
|
|
||||||
142,Aerodactyl,,
|
|
||||||
143,Snorlax,,
|
|
||||||
144,Articuno,,
|
|
||||||
145,Zapdos,,
|
|
||||||
146,Moltres,,
|
|
||||||
147,Dratini,,
|
|
||||||
148,Dragonair,,
|
|
||||||
149,Dragonite,,
|
|
||||||
150,Mewtwo,,
|
|
||||||
151,Mew,,
|
|
||||||
|
@@ -1,203 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Treecko,,
|
|
||||||
2,Grovyle,,
|
|
||||||
3,Sceptile,,
|
|
||||||
4,Torchic,,
|
|
||||||
5,Combusken,,
|
|
||||||
6,Blaziken,,
|
|
||||||
7,Mudkip,,
|
|
||||||
8,Marshtomp,,
|
|
||||||
9,Swampert,,
|
|
||||||
10,Poochyena,,
|
|
||||||
11,Mightyena,,
|
|
||||||
12,Zigzagoon,,
|
|
||||||
13,Linoone,,
|
|
||||||
14,Wurmple,,
|
|
||||||
15,Silcoon,,
|
|
||||||
16,Beautifly,,
|
|
||||||
17,Cascoon,,
|
|
||||||
18,Dustox,,
|
|
||||||
19,Lotad,,
|
|
||||||
20,Lombre,,
|
|
||||||
21,Ludicolo,,
|
|
||||||
22,Seedot,,
|
|
||||||
23,Nuzleaf,,
|
|
||||||
24,Shiftry,,
|
|
||||||
25,Taillow,,
|
|
||||||
26,Swellow,,
|
|
||||||
27,Wingull,,
|
|
||||||
28,Pelipper,,
|
|
||||||
29,Ralts,,
|
|
||||||
30,Kirlia,,
|
|
||||||
31,Gardevoir,,
|
|
||||||
32,Surskit,,
|
|
||||||
33,Masquerain,,
|
|
||||||
34,Shroomish,,
|
|
||||||
35,Breloom,,
|
|
||||||
36,Slakoth,,
|
|
||||||
37,Vigoroth,,
|
|
||||||
38,Slaking,,
|
|
||||||
39,Abra,,
|
|
||||||
40,Kadabra,,
|
|
||||||
41,Alakazam,,
|
|
||||||
42,Nincada,,
|
|
||||||
43,Ninjask,,
|
|
||||||
44,Shedinja,,
|
|
||||||
45,Whismur,,
|
|
||||||
46,Loudred,,
|
|
||||||
47,Exploud,,
|
|
||||||
48,Makuhita,,
|
|
||||||
49,Hariyama,,
|
|
||||||
50,Goldeen,,
|
|
||||||
51,Seaking,,
|
|
||||||
52,Magikarp,,
|
|
||||||
53,Gyarados,,
|
|
||||||
54,Azurill,,
|
|
||||||
55,Marill,,
|
|
||||||
56,Azumarill,,
|
|
||||||
57,Geodude,,
|
|
||||||
58,Graveler,,
|
|
||||||
59,Golem,,
|
|
||||||
60,Nosepass,,
|
|
||||||
61,Skitty,,
|
|
||||||
62,Delcatty,,
|
|
||||||
63,Zubat,,
|
|
||||||
64,Golbat,,
|
|
||||||
65,Crobat,,
|
|
||||||
66,Tentacool,,
|
|
||||||
67,Tentacruel,,
|
|
||||||
68,Sableye,,
|
|
||||||
69,Mawile,,
|
|
||||||
70,Aron,,
|
|
||||||
71,Lairon,,
|
|
||||||
72,Aggron,,
|
|
||||||
73,Machop,,
|
|
||||||
74,Machoke,,
|
|
||||||
75,Machamp,,
|
|
||||||
76,Meditite,,
|
|
||||||
77,Medicham,,
|
|
||||||
78,Electrike,,
|
|
||||||
79,Manectric,,
|
|
||||||
80,Plusle,,
|
|
||||||
81,Minun,,
|
|
||||||
82,Magnemite,,
|
|
||||||
83,Magneton,,
|
|
||||||
84,Voltorb,,
|
|
||||||
85,Electrode,,
|
|
||||||
86,Volbeat,,
|
|
||||||
87,Illumise,,
|
|
||||||
88,Oddish,,
|
|
||||||
89,Gloom,,
|
|
||||||
90,Vileplume,,
|
|
||||||
91,Bellossom,,
|
|
||||||
92,Doduo,,
|
|
||||||
93,Dodrio,,
|
|
||||||
94,Roselia,,
|
|
||||||
95,Gulpin,,
|
|
||||||
96,Swalot,,
|
|
||||||
97,Carvanha,,
|
|
||||||
98,Sharpedo,,
|
|
||||||
99,Wailmer,,
|
|
||||||
100,Wailord,,
|
|
||||||
101,Numel,,
|
|
||||||
102,Camerupt,,
|
|
||||||
103,Slugma,,
|
|
||||||
104,Magcargo,,
|
|
||||||
105,Torkoal,,
|
|
||||||
106,Grimer,,
|
|
||||||
107,Muk,,
|
|
||||||
108,Koffing,,
|
|
||||||
109,Weezing,,
|
|
||||||
110,Spoink,,
|
|
||||||
111,Grumpig,,
|
|
||||||
112,Sandshrew,,
|
|
||||||
113,Sandslash,,
|
|
||||||
114,Spinda,,
|
|
||||||
115,Skarmory,,
|
|
||||||
116,Trapinch,,
|
|
||||||
117,Vibrava,,
|
|
||||||
118,Flygon,,
|
|
||||||
119,Cacnea,,
|
|
||||||
120,Cacturne,,
|
|
||||||
121,Swablu,,
|
|
||||||
122,Altaria,,
|
|
||||||
123,Zangoose,,
|
|
||||||
124,Seviper,,
|
|
||||||
125,Lunatone,,
|
|
||||||
126,Solrock,,
|
|
||||||
127,Barboach,,
|
|
||||||
128,Whiscash,,
|
|
||||||
129,Corphish,,
|
|
||||||
130,Crawdaunt,,
|
|
||||||
131,Baltoy,,
|
|
||||||
132,Claydol,,
|
|
||||||
133,Lileep,,
|
|
||||||
134,Cradily,,
|
|
||||||
135,Anorith,,
|
|
||||||
136,Armaldo,,
|
|
||||||
137,Igglybuff,,
|
|
||||||
138,Jigglypuff,,
|
|
||||||
139,Wigglytuff,,
|
|
||||||
140,Feebas,,
|
|
||||||
141,Milotic,,
|
|
||||||
142,Castform,,
|
|
||||||
143,Staryu,,
|
|
||||||
144,Starmie,,
|
|
||||||
145,Kecleon,,
|
|
||||||
146,Shuppet,,
|
|
||||||
147,Banette,,
|
|
||||||
148,Duskull,,
|
|
||||||
149,Dusclops,,
|
|
||||||
150,Tropius,,
|
|
||||||
151,Chimecho,,
|
|
||||||
152,Absol,,
|
|
||||||
153,Vulpix,,
|
|
||||||
154,Ninetales,,
|
|
||||||
155,Pichu,,
|
|
||||||
156,Pikachu,,
|
|
||||||
157,Raichu,,
|
|
||||||
158,Psyduck,,
|
|
||||||
159,Golduck,,
|
|
||||||
160,Wynaut,,
|
|
||||||
161,Wobbuffet,,
|
|
||||||
162,Natu,,
|
|
||||||
163,Xatu,,
|
|
||||||
164,Girafarig,,
|
|
||||||
165,Phanpy,,
|
|
||||||
166,Donphan,,
|
|
||||||
167,Pinsir,,
|
|
||||||
168,Heracross,,
|
|
||||||
169,Rhyhorn,,
|
|
||||||
170,Rhydon,,
|
|
||||||
171,Snorunt,,
|
|
||||||
172,Glalie,,
|
|
||||||
173,Spheal,,
|
|
||||||
174,Sealeo,,
|
|
||||||
175,Walrein,,
|
|
||||||
176,Clamperl,,
|
|
||||||
177,Huntail,,
|
|
||||||
178,Gorebyss,,
|
|
||||||
179,Relicanth,,
|
|
||||||
180,Corsola,,
|
|
||||||
181,Chinchou,,
|
|
||||||
182,Lanturn,,
|
|
||||||
183,Luvdisc,,
|
|
||||||
184,Horsea,,
|
|
||||||
185,Seadra,,
|
|
||||||
186,Kingdra,,
|
|
||||||
187,Bagon,,
|
|
||||||
188,Shelgon,,
|
|
||||||
189,Salamence,,
|
|
||||||
190,Beldum,,
|
|
||||||
191,Metang,,
|
|
||||||
192,Metagross,,
|
|
||||||
193,Regirock,,
|
|
||||||
194,Regice,,
|
|
||||||
195,Registeel,,
|
|
||||||
196,Latias,,
|
|
||||||
197,Latios,,
|
|
||||||
198,Kyogre,,
|
|
||||||
199,Groudon,,
|
|
||||||
200,Rayquaza,,
|
|
||||||
201,Jirachi,,
|
|
||||||
202,Deoxys,,
|
|
||||||
|
@@ -1,244 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Doduo,,
|
|
||||||
2,Dodrio,,
|
|
||||||
3,Exeggcute,,
|
|
||||||
4,Exeggutor,,
|
|
||||||
5,Rhyhorn,,
|
|
||||||
6,Rhydon,,
|
|
||||||
7,Rhyperior,,
|
|
||||||
8,Venonat,,
|
|
||||||
9,Venomoth,,
|
|
||||||
10,Elekid,,
|
|
||||||
11,Electabuzz,,
|
|
||||||
12,Electivire,,
|
|
||||||
13,Magby,,
|
|
||||||
14,Magmar,,
|
|
||||||
15,Magmortar,,
|
|
||||||
16,Happiny,,
|
|
||||||
17,Chansey,,
|
|
||||||
18,Blissey,,
|
|
||||||
19,Scyther,,
|
|
||||||
20,Scizor,,
|
|
||||||
21,Kleavor,,
|
|
||||||
22,Tauros,,
|
|
||||||
23,Blitzle,,
|
|
||||||
24,Zebstrika,,
|
|
||||||
25,Girafarig,,
|
|
||||||
26,Farigiraf,,
|
|
||||||
27,Sandile,,
|
|
||||||
28,Krokorok,,
|
|
||||||
29,Krookodile,,
|
|
||||||
30,Rellor,,
|
|
||||||
31,Rabsca,,
|
|
||||||
32,Rufflet,,
|
|
||||||
33,Braviary,,
|
|
||||||
34,Vullaby,,
|
|
||||||
35,Mandibuzz,,
|
|
||||||
36,Litleo,,
|
|
||||||
37,Pyroar,,
|
|
||||||
38,Deerling,,
|
|
||||||
39,Sawsbuck,,
|
|
||||||
40,Smeargle,,
|
|
||||||
41,Rotom,,
|
|
||||||
42,Milcery,,
|
|
||||||
43,Alcremie,,
|
|
||||||
44,Trapinch,,
|
|
||||||
45,Vibrava,,
|
|
||||||
46,Flygon,,
|
|
||||||
47,Pikipek,,
|
|
||||||
48,Trumbeak,,
|
|
||||||
49,Toucannon,,
|
|
||||||
50,Tentacool,,
|
|
||||||
51,Tentacruel,,
|
|
||||||
52,Horsea,,
|
|
||||||
53,Seadra,,
|
|
||||||
54,Kingdra,,
|
|
||||||
55,Bruxish,,
|
|
||||||
56,Cottonee,,
|
|
||||||
57,Whimsicott,,
|
|
||||||
58,Comfey,,
|
|
||||||
59,Slakoth,,
|
|
||||||
60,Vigoroth,,
|
|
||||||
61,Slaking,,
|
|
||||||
62,Oddish,,
|
|
||||||
63,Gloom,,
|
|
||||||
64,Vileplume,,
|
|
||||||
65,Bellossom,,
|
|
||||||
66,Diglett,,
|
|
||||||
67,Dugtrio,,
|
|
||||||
68,Grimer,,
|
|
||||||
69,Muk,,
|
|
||||||
70,Zangoose,,
|
|
||||||
71,Seviper,,
|
|
||||||
72,Crabrawler,,
|
|
||||||
73,Crabominable,,
|
|
||||||
74,Oricorio,,
|
|
||||||
75,Slowpoke,,
|
|
||||||
76,Slowbro,,
|
|
||||||
77,Slowking,,
|
|
||||||
78,Chinchou,,
|
|
||||||
79,Lanturn,,
|
|
||||||
80,Inkay,,
|
|
||||||
81,Malamar,,
|
|
||||||
82,Luvdisc,,
|
|
||||||
83,Finneon,,
|
|
||||||
84,Lumineon,,
|
|
||||||
85,Alomomola,,
|
|
||||||
86,Torkoal,,
|
|
||||||
87,Fletchling,,
|
|
||||||
88,Fletchinder,,
|
|
||||||
89,Talonflame,,
|
|
||||||
90,Dewpider,,
|
|
||||||
91,Araquanid,,
|
|
||||||
92,Tyrogue,,
|
|
||||||
93,Hitmonlee,,
|
|
||||||
94,Hitmonchan,,
|
|
||||||
95,Hitmontop,,
|
|
||||||
96,Geodude,,
|
|
||||||
97,Graveler,,
|
|
||||||
98,Golem,,
|
|
||||||
99,Drilbur,,
|
|
||||||
100,Excadrill,,
|
|
||||||
101,Gothita,,
|
|
||||||
102,Gothorita,,
|
|
||||||
103,Gothitelle,,
|
|
||||||
104,Espurr,,
|
|
||||||
105,Meowstic,,
|
|
||||||
106,Minior,,
|
|
||||||
107,Cranidos,,
|
|
||||||
108,Rampardos,,
|
|
||||||
109,Shieldon,,
|
|
||||||
110,Bastiodon,,
|
|
||||||
111,Minccino,,
|
|
||||||
112,Cinccino,,
|
|
||||||
113,Skarmory,,
|
|
||||||
114,Swablu,,
|
|
||||||
115,Altaria,,
|
|
||||||
116,Magnemite,,
|
|
||||||
117,Magneton,,
|
|
||||||
118,Magnezone,,
|
|
||||||
119,Plusle,,
|
|
||||||
120,Minun,,
|
|
||||||
121,Scraggy,,
|
|
||||||
122,Scrafty,,
|
|
||||||
123,Golett,,
|
|
||||||
124,Golurk,,
|
|
||||||
125,Numel,,
|
|
||||||
126,Camerupt,,
|
|
||||||
127,Sinistea,,
|
|
||||||
128,Polteageist,,
|
|
||||||
129,Porygon,,
|
|
||||||
130,Porygon2,,
|
|
||||||
131,Porygon-Z,,
|
|
||||||
132,Joltik,,
|
|
||||||
133,Galvantula,,
|
|
||||||
134,Tynamo,,
|
|
||||||
135,Eelektrik,,
|
|
||||||
136,Eelektross,,
|
|
||||||
137,Beldum,,
|
|
||||||
138,Metang,,
|
|
||||||
139,Metagross,,
|
|
||||||
140,Axew,,
|
|
||||||
141,Fraxure,,
|
|
||||||
142,Haxorus,,
|
|
||||||
143,Seel,,
|
|
||||||
144,Dewgong,,
|
|
||||||
145,Lapras,,
|
|
||||||
146,Qwilfish,,
|
|
||||||
147,Overqwil,,
|
|
||||||
148,Solosis,,
|
|
||||||
149,Duosion,,
|
|
||||||
150,Reuniclus,,
|
|
||||||
151,Snubbull,,
|
|
||||||
152,Granbull,,
|
|
||||||
153,Cubchoo,,
|
|
||||||
154,Beartic,,
|
|
||||||
155,Sandshrew,,
|
|
||||||
156,Sandslash,,
|
|
||||||
157,Vulpix,,
|
|
||||||
158,Ninetales,,
|
|
||||||
159,Snover,,
|
|
||||||
160,Abomasnow,,
|
|
||||||
161,Duraludon,,
|
|
||||||
162,Archaludon,,
|
|
||||||
163,Hydrapple,,
|
|
||||||
164,Bulbasaur,,
|
|
||||||
165,Ivysaur,,
|
|
||||||
166,Venusaur,,
|
|
||||||
167,Charmander,,
|
|
||||||
168,Charmeleon,,
|
|
||||||
169,Charizard,,
|
|
||||||
170,Squirtle,,
|
|
||||||
171,Wartortle,,
|
|
||||||
172,Blastoise,,
|
|
||||||
173,Chikorita,,
|
|
||||||
174,Bayleef,,
|
|
||||||
175,Meganium,,
|
|
||||||
176,Cyndaquil,,
|
|
||||||
177,Quilava,,
|
|
||||||
178,Typhlosion,,
|
|
||||||
179,Totodile,,
|
|
||||||
180,Croconaw,,
|
|
||||||
181,Feraligatr,,
|
|
||||||
182,Treecko,,
|
|
||||||
183,Grovyle,,
|
|
||||||
184,Sceptile,,
|
|
||||||
185,Torchic,,
|
|
||||||
186,Combusken,,
|
|
||||||
187,Blaziken,,
|
|
||||||
188,Mudkip,,
|
|
||||||
189,Marshtomp,,
|
|
||||||
190,Swampert,,
|
|
||||||
191,Turtwig,,
|
|
||||||
192,Grotle,,
|
|
||||||
193,Torterra,,
|
|
||||||
194,Chimchar,,
|
|
||||||
195,Monferno,,
|
|
||||||
196,Infernape,,
|
|
||||||
197,Piplup,,
|
|
||||||
198,Prinplup,,
|
|
||||||
199,Empoleon,,
|
|
||||||
200,Snivy,,
|
|
||||||
201,Servine,,
|
|
||||||
202,Serperior,,
|
|
||||||
203,Tepig,,
|
|
||||||
204,Pignite,,
|
|
||||||
205,Emboar,,
|
|
||||||
206,Oshawott,,
|
|
||||||
207,Dewott,,
|
|
||||||
208,Samurott,,
|
|
||||||
209,Chespin,,
|
|
||||||
210,Quilladin,,
|
|
||||||
211,Chesnaught,,
|
|
||||||
212,Fennekin,,
|
|
||||||
213,Braixen,,
|
|
||||||
214,Delphox,,
|
|
||||||
215,Froakie,,
|
|
||||||
216,Frogadier,,
|
|
||||||
217,Greninja,,
|
|
||||||
218,Rowlet,,
|
|
||||||
219,Dartrix,,
|
|
||||||
220,Decidueye,,
|
|
||||||
221,Litten,,
|
|
||||||
222,Torracat,,
|
|
||||||
223,Incineroar,,
|
|
||||||
224,Popplio,,
|
|
||||||
225,Brionne,,
|
|
||||||
226,Primarina,,
|
|
||||||
227,Grookey,,
|
|
||||||
228,Thwackey,,
|
|
||||||
229,Rillaboom,,
|
|
||||||
230,Scorbunny,,
|
|
||||||
231,Raboot,,
|
|
||||||
232,Cinderace,,
|
|
||||||
233,Sobble,,
|
|
||||||
234,Drizzile,,
|
|
||||||
235,Inteleon,,
|
|
||||||
236,Gouging Fire,,
|
|
||||||
237,Raging Bolt,,
|
|
||||||
238,Iron Crown,,
|
|
||||||
239,Iron Boulder,,
|
|
||||||
240,Terapagos,,
|
|
||||||
241,Walking Wake,,
|
|
||||||
242,Iron Leaves,,
|
|
||||||
243,Pecharunt,,
|
|
||||||
|
@@ -1,201 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Spinarak,,
|
|
||||||
2,Ariados,,
|
|
||||||
3,Yanma,,
|
|
||||||
4,Yanmega,,
|
|
||||||
5,Wooper,,
|
|
||||||
6,Quagsire,,
|
|
||||||
7,Poochyena,,
|
|
||||||
8,Mightyena,,
|
|
||||||
9,Volbeat,,
|
|
||||||
10,Illumise,,
|
|
||||||
11,Corphish,,
|
|
||||||
12,Crawdaunt,,
|
|
||||||
13,Sewaddle,,
|
|
||||||
14,Swadloon,,
|
|
||||||
15,Leavanny,,
|
|
||||||
16,Cutiefly,,
|
|
||||||
17,Ribombee,,
|
|
||||||
18,Ekans,,
|
|
||||||
19,Arbok,,
|
|
||||||
20,Pichu,,
|
|
||||||
21,Pikachu,,
|
|
||||||
22,Raichu,,
|
|
||||||
23,Bellsprout,,
|
|
||||||
24,Weepinbell,,
|
|
||||||
25,Victreebel,,
|
|
||||||
26,Sentret,,
|
|
||||||
27,Furret,,
|
|
||||||
28,Starly,,
|
|
||||||
29,Staravia,,
|
|
||||||
30,Staraptor,,
|
|
||||||
31,Fomantis,,
|
|
||||||
32,Lurantis,,
|
|
||||||
33,Applin,,
|
|
||||||
34,Flapple,,
|
|
||||||
35,Appletun,,
|
|
||||||
36,Dipplin,,
|
|
||||||
37,Vulpix,,
|
|
||||||
38,Ninetales,,
|
|
||||||
39,Poliwag,,
|
|
||||||
40,Poliwhirl,,
|
|
||||||
41,Poliwrath,,
|
|
||||||
42,Politoed,,
|
|
||||||
43,Magikarp,,
|
|
||||||
44,Gyarados,,
|
|
||||||
45,Hoothoot,,
|
|
||||||
46,Noctowl,,
|
|
||||||
47,Aipom,,
|
|
||||||
48,Ambipom,,
|
|
||||||
49,Heracross,,
|
|
||||||
50,Swinub,,
|
|
||||||
51,Piloswine,,
|
|
||||||
52,Mamoswine,,
|
|
||||||
53,Stantler,,
|
|
||||||
54,Seedot,,
|
|
||||||
55,Nuzleaf,,
|
|
||||||
56,Shiftry,,
|
|
||||||
57,Ralts,,
|
|
||||||
58,Kirlia,,
|
|
||||||
59,Gardevoir,,
|
|
||||||
60,Gallade,,
|
|
||||||
61,Kricketot,,
|
|
||||||
62,Kricketune,,
|
|
||||||
63,Pachirisu,,
|
|
||||||
64,Riolu,,
|
|
||||||
65,Lucario,,
|
|
||||||
66,Petilil,,
|
|
||||||
67,Lilligant,,
|
|
||||||
68,Phantump,,
|
|
||||||
69,Trevenant,,
|
|
||||||
70,Rockruff,,
|
|
||||||
71,Lycanroc,,
|
|
||||||
72,Skwovet,,
|
|
||||||
73,Greedent,,
|
|
||||||
74,Toedscool,,
|
|
||||||
75,Toedscruel,,
|
|
||||||
76,Poltchageist,,
|
|
||||||
77,Sinistcha,,
|
|
||||||
78,Growlithe,,
|
|
||||||
79,Arcanine,,
|
|
||||||
80,Geodude,,
|
|
||||||
81,Graveler,,
|
|
||||||
82,Golem,,
|
|
||||||
83,Bonsly,,
|
|
||||||
84,Sudowoodo,,
|
|
||||||
85,Timburr,,
|
|
||||||
86,Gurdurr,,
|
|
||||||
87,Conkeldurr,,
|
|
||||||
88,Noibat,,
|
|
||||||
89,Noivern,,
|
|
||||||
90,Arrokuda,,
|
|
||||||
91,Barraskewda,,
|
|
||||||
92,Hatenna,,
|
|
||||||
93,Hattrem,,
|
|
||||||
94,Hatterene,,
|
|
||||||
95,Morpeko,,
|
|
||||||
96,Orthworm,,
|
|
||||||
97,Tandemaus,,
|
|
||||||
98,Maushold,,
|
|
||||||
99,Mankey,,
|
|
||||||
100,Primeape,,
|
|
||||||
101,Annihilape,,
|
|
||||||
102,Munchlax,,
|
|
||||||
103,Snorlax,,
|
|
||||||
104,Lotad,,
|
|
||||||
105,Lombre,,
|
|
||||||
106,Ludicolo,,
|
|
||||||
107,Nosepass,,
|
|
||||||
108,Probopass,,
|
|
||||||
109,Shinx,,
|
|
||||||
110,Luxio,,
|
|
||||||
111,Luxray,,
|
|
||||||
112,Grubbin,,
|
|
||||||
113,Charjabug,,
|
|
||||||
114,Vikavolt,,
|
|
||||||
115,Oricorio,,
|
|
||||||
116,Sandshrew,,
|
|
||||||
117,Sandslash,,
|
|
||||||
118,Gastly,,
|
|
||||||
119,Haunter,,
|
|
||||||
120,Gengar,,
|
|
||||||
121,Gligar,,
|
|
||||||
122,Gliscor,,
|
|
||||||
123,Houndour,,
|
|
||||||
124,Houndoom,,
|
|
||||||
125,Spoink,,
|
|
||||||
126,Grumpig,,
|
|
||||||
127,Vullaby,,
|
|
||||||
128,Mandibuzz,,
|
|
||||||
129,Mudbray,,
|
|
||||||
130,Mudsdale,,
|
|
||||||
131,Jangmo-o,,
|
|
||||||
132,Hakamo-o,,
|
|
||||||
133,Kommo-o,,
|
|
||||||
134,Bombirdier,,
|
|
||||||
135,Koffing,,
|
|
||||||
136,Weezing,,
|
|
||||||
137,Mienfoo,,
|
|
||||||
138,Mienshao,,
|
|
||||||
139,Duskull,,
|
|
||||||
140,Dusclops,,
|
|
||||||
141,Dusknoir,,
|
|
||||||
142,Chingling,,
|
|
||||||
143,Chimecho,,
|
|
||||||
144,Slugma,,
|
|
||||||
145,Magcargo,,
|
|
||||||
146,Litwick,,
|
|
||||||
147,Lampent,,
|
|
||||||
148,Chandelure,,
|
|
||||||
149,Surskit,,
|
|
||||||
150,Masquerain,,
|
|
||||||
151,Cleffa,,
|
|
||||||
152,Clefairy,,
|
|
||||||
153,Clefable,,
|
|
||||||
154,Bronzor,,
|
|
||||||
155,Bronzong,,
|
|
||||||
156,Glimmet,,
|
|
||||||
157,Glimmora,,
|
|
||||||
158,Feebas,,
|
|
||||||
159,Milotic,,
|
|
||||||
160,Dunsparce,,
|
|
||||||
161,Dudunsparce,,
|
|
||||||
162,Barboach,,
|
|
||||||
163,Whiscash,,
|
|
||||||
164,Gible,,
|
|
||||||
165,Gabite,,
|
|
||||||
166,Garchomp,,
|
|
||||||
167,Carbink,,
|
|
||||||
168,Salandit,,
|
|
||||||
169,Salazzle,,
|
|
||||||
170,Sneasel,,
|
|
||||||
171,Weavile,,
|
|
||||||
172,Snorunt,,
|
|
||||||
173,Glalie,,
|
|
||||||
174,Froslass,,
|
|
||||||
175,Tynamo,,
|
|
||||||
176,Eelektrik,,
|
|
||||||
177,Eelektross,,
|
|
||||||
178,Goomy,,
|
|
||||||
179,Sliggoo,,
|
|
||||||
180,Goodra,,
|
|
||||||
181,Ducklett,,
|
|
||||||
182,Swanna,,
|
|
||||||
183,Chewtle,,
|
|
||||||
184,Drednaw,,
|
|
||||||
185,Cramorant,,
|
|
||||||
186,Pawniard,,
|
|
||||||
187,Bisharp,,
|
|
||||||
188,Kingambit,,
|
|
||||||
189,Mimikyu,,
|
|
||||||
190,Impidimp,,
|
|
||||||
191,Morgrem,,
|
|
||||||
192,Grimmsnarl,,
|
|
||||||
193,Indeedee,,
|
|
||||||
194,Basculin,,
|
|
||||||
195,Basculegion,,
|
|
||||||
196,Ursaluna,,
|
|
||||||
197,Okidogi,,
|
|
||||||
198,Munkidori,,
|
|
||||||
199,Fezandipiti,,
|
|
||||||
200,Ogerpon,,
|
|
||||||
|
@@ -1,401 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Sprigatito,,
|
|
||||||
2,Floragato,,
|
|
||||||
3,Meowscarada,,
|
|
||||||
4,Fuecoco,,
|
|
||||||
5,Crocalor,,
|
|
||||||
6,Skeledirge,,
|
|
||||||
7,Quaxly,,
|
|
||||||
8,Quaxwell,,
|
|
||||||
9,Quaquaval,,
|
|
||||||
10,Lechonk,,
|
|
||||||
11,Oinkologne,,
|
|
||||||
12,Tarountula,,
|
|
||||||
13,Spidops,,
|
|
||||||
14,Nymble,,
|
|
||||||
15,Lokix,,
|
|
||||||
16,Hoppip,,
|
|
||||||
17,Skiploom,,
|
|
||||||
18,Jumpluff,,
|
|
||||||
19,Fletchling,,
|
|
||||||
20,Fletchinder,,
|
|
||||||
21,Talonflame,,
|
|
||||||
22,Pawmi,,
|
|
||||||
23,Pawmo,,
|
|
||||||
24,Pawmot,,
|
|
||||||
25,Houndour,,
|
|
||||||
26,Houndoom,,
|
|
||||||
27,Yungoos,,
|
|
||||||
28,Gumshoos,,
|
|
||||||
29,Skwovet,,
|
|
||||||
30,Greedent,,
|
|
||||||
31,Sunkern,,
|
|
||||||
32,Sunflora,,
|
|
||||||
33,Kricketot,,
|
|
||||||
34,Kricketune,,
|
|
||||||
35,Scatterbug,,
|
|
||||||
36,Spewpa,,
|
|
||||||
37,Vivillon,,
|
|
||||||
38,Combee,,
|
|
||||||
39,Vespiquen,,
|
|
||||||
40,Rookidee,,
|
|
||||||
41,Corvisquire,,
|
|
||||||
42,Corviknight,,
|
|
||||||
43,Happiny,,
|
|
||||||
44,Chansey,,
|
|
||||||
45,Blissey,,
|
|
||||||
46,Azurill,,
|
|
||||||
47,Marill,,
|
|
||||||
48,Azumarill,,
|
|
||||||
49,Surskit,,
|
|
||||||
50,Masquerain,,
|
|
||||||
51,Buizel,,
|
|
||||||
52,Floatzel,,
|
|
||||||
53,Wooper,,
|
|
||||||
54,Clodsire,,
|
|
||||||
55,Psyduck,,
|
|
||||||
56,Golduck,,
|
|
||||||
57,Chewtle,,
|
|
||||||
58,Drednaw,,
|
|
||||||
59,Igglybuff,,
|
|
||||||
60,Jigglypuff,,
|
|
||||||
61,Wigglytuff,,
|
|
||||||
62,Ralts,,
|
|
||||||
63,Kirlia,,
|
|
||||||
64,Gardevoir,,
|
|
||||||
65,Gallade,,
|
|
||||||
66,Drowzee,,
|
|
||||||
67,Hypno,,
|
|
||||||
68,Gastly,,
|
|
||||||
69,Haunter,,
|
|
||||||
70,Gengar,,
|
|
||||||
71,Tandemaus,,
|
|
||||||
72,Maushold,,
|
|
||||||
73,Pichu,,
|
|
||||||
74,Pikachu,,
|
|
||||||
75,Raichu,,
|
|
||||||
76,Fidough,,
|
|
||||||
77,Dachsbun,,
|
|
||||||
78,Slakoth,,
|
|
||||||
79,Vigoroth,,
|
|
||||||
80,Slaking,,
|
|
||||||
81,Bounsweet,,
|
|
||||||
82,Steenee,,
|
|
||||||
83,Tsareena,,
|
|
||||||
84,Smoliv,,
|
|
||||||
85,Dolliv,,
|
|
||||||
86,Arboliva,,
|
|
||||||
87,Bonsly,,
|
|
||||||
88,Sudowoodo,,
|
|
||||||
89,Rockruff,,
|
|
||||||
90,Lycanroc,,
|
|
||||||
91,Rolycoly,,
|
|
||||||
92,Carkol,,
|
|
||||||
93,Coalossal,,
|
|
||||||
94,Shinx,,
|
|
||||||
95,Luxio,,
|
|
||||||
96,Luxray,,
|
|
||||||
97,Starly,,
|
|
||||||
98,Staravia,,
|
|
||||||
99,Staraptor,,
|
|
||||||
100,Oricorio,,
|
|
||||||
101,Mareep,,
|
|
||||||
102,Flaaffy,,
|
|
||||||
103,Ampharos,,
|
|
||||||
104,Petilil,,
|
|
||||||
105,Lilligant,,
|
|
||||||
106,Shroomish,,
|
|
||||||
107,Breloom,,
|
|
||||||
108,Applin,,
|
|
||||||
109,Flapple,,
|
|
||||||
110,Appletun,,
|
|
||||||
111,Spoink,,
|
|
||||||
112,Grumpig,,
|
|
||||||
113,Squawkabilly,,
|
|
||||||
114,Misdreavus,,
|
|
||||||
115,Mismagius,,
|
|
||||||
116,Makuhita,,
|
|
||||||
117,Hariyama,,
|
|
||||||
118,Crabrawler,,
|
|
||||||
119,Crabominable,,
|
|
||||||
120,Salandit,,
|
|
||||||
121,Salazzle,,
|
|
||||||
122,Phanpy,,
|
|
||||||
123,Donphan,,
|
|
||||||
124,Cufant,,
|
|
||||||
125,Copperajah,,
|
|
||||||
126,Gible,,
|
|
||||||
127,Gabite,,
|
|
||||||
128,Garchomp,,
|
|
||||||
129,Nacli,,
|
|
||||||
130,Naclstack,,
|
|
||||||
131,Garganacl,,
|
|
||||||
132,Wingull,,
|
|
||||||
133,Pelipper,,
|
|
||||||
134,Magikarp,,
|
|
||||||
135,Gyarados,,
|
|
||||||
136,Arrokuda,,
|
|
||||||
137,Barraskewda,,
|
|
||||||
138,Basculin,,
|
|
||||||
139,Gulpin,,
|
|
||||||
140,Swalot,,
|
|
||||||
141,Meowth,,
|
|
||||||
142,Persian,,
|
|
||||||
143,Drifloon,,
|
|
||||||
144,Drifblim,,
|
|
||||||
145,Flabébé,,
|
|
||||||
146,Floette,,
|
|
||||||
147,Florges,,
|
|
||||||
148,Diglett,,
|
|
||||||
149,Dugtrio,,
|
|
||||||
150,Torkoal,,
|
|
||||||
151,Numel,,
|
|
||||||
152,Camerupt,,
|
|
||||||
153,Bronzor,,
|
|
||||||
154,Bronzong,,
|
|
||||||
155,Axew,,
|
|
||||||
156,Fraxure,,
|
|
||||||
157,Haxorus,,
|
|
||||||
158,Mankey,,
|
|
||||||
159,Primeape,,
|
|
||||||
160,Annihilape,,
|
|
||||||
161,Meditite,,
|
|
||||||
162,Medicham,,
|
|
||||||
163,Riolu,,
|
|
||||||
164,Lucario,,
|
|
||||||
165,Charcadet,,
|
|
||||||
166,Armarouge,,
|
|
||||||
167,Ceruledge,,
|
|
||||||
168,Barboach,,
|
|
||||||
169,Whiscash,,
|
|
||||||
170,Tadbulb,,
|
|
||||||
171,Bellibolt,,
|
|
||||||
172,Goomy,,
|
|
||||||
173,Sliggoo,,
|
|
||||||
174,Goodra,,
|
|
||||||
175,Croagunk,,
|
|
||||||
176,Toxicroak,,
|
|
||||||
177,Wattrel,,
|
|
||||||
178,Kilowattrel,,
|
|
||||||
179,Eevee,,
|
|
||||||
180,Vaporeon,,
|
|
||||||
181,Jolteon,,
|
|
||||||
182,Flareon,,
|
|
||||||
183,Espeon,,
|
|
||||||
184,Umbreon,,
|
|
||||||
185,Leafeon,,
|
|
||||||
186,Glaceon,,
|
|
||||||
187,Sylveon,,
|
|
||||||
188,Dunsparce,,
|
|
||||||
189,Dudunsparce,,
|
|
||||||
190,Deerling,,
|
|
||||||
191,Sawsbuck,,
|
|
||||||
192,Girafarig,,
|
|
||||||
193,Farigiraf,,
|
|
||||||
194,Grimer,,
|
|
||||||
195,Muk,,
|
|
||||||
196,Maschiff,,
|
|
||||||
197,Mabosstiff,,
|
|
||||||
198,Toxel,,
|
|
||||||
199,Toxtricity,,
|
|
||||||
200,Dedenne,,
|
|
||||||
201,Pachirisu,,
|
|
||||||
202,Shroodle,,
|
|
||||||
203,Grafaiai,,
|
|
||||||
204,Stantler,,
|
|
||||||
205,Foongus,,
|
|
||||||
206,Amoonguss,,
|
|
||||||
207,Voltorb,,
|
|
||||||
208,Electrode,,
|
|
||||||
209,Magnemite,,
|
|
||||||
210,Magneton,,
|
|
||||||
211,Magnezone,,
|
|
||||||
212,Ditto,,
|
|
||||||
213,Growlithe,,
|
|
||||||
214,Arcanine,,
|
|
||||||
215,Teddiursa,,
|
|
||||||
216,Ursaring,,
|
|
||||||
217,Zangoose,,
|
|
||||||
218,Seviper,,
|
|
||||||
219,Swablu,,
|
|
||||||
220,Altaria,,
|
|
||||||
221,Skiddo,,
|
|
||||||
222,Gogoat,,
|
|
||||||
223,Tauros,,
|
|
||||||
224,Litleo,,
|
|
||||||
225,Pyroar,,
|
|
||||||
226,Stunky,,
|
|
||||||
227,Skuntank,,
|
|
||||||
228,Zorua,,
|
|
||||||
229,Zoroark,,
|
|
||||||
230,Sneasel,,
|
|
||||||
231,Weavile,,
|
|
||||||
232,Murkrow,,
|
|
||||||
233,Honchkrow,,
|
|
||||||
234,Gothita,,
|
|
||||||
235,Gothorita,,
|
|
||||||
236,Gothitelle,,
|
|
||||||
237,Sinistea,,
|
|
||||||
238,Polteageist,,
|
|
||||||
239,Mimikyu,,
|
|
||||||
240,Klefki,,
|
|
||||||
241,Indeedee,,
|
|
||||||
242,Bramblin,,
|
|
||||||
243,Brambleghast,,
|
|
||||||
244,Toedscool,,
|
|
||||||
245,Toedscruel,,
|
|
||||||
246,Tropius,,
|
|
||||||
247,Fomantis,,
|
|
||||||
248,Lurantis,,
|
|
||||||
249,Klawf,,
|
|
||||||
250,Capsakid,,
|
|
||||||
251,Scovillain,,
|
|
||||||
252,Cacnea,,
|
|
||||||
253,Cacturne,,
|
|
||||||
254,Rellor,,
|
|
||||||
255,Rabsca,,
|
|
||||||
256,Venonat,,
|
|
||||||
257,Venomoth,,
|
|
||||||
258,Pineco,,
|
|
||||||
259,Forretress,,
|
|
||||||
260,Scyther,,
|
|
||||||
261,Scizor,,
|
|
||||||
262,Heracross,,
|
|
||||||
263,Flittle,,
|
|
||||||
264,Espathra,,
|
|
||||||
265,Hippopotas,,
|
|
||||||
266,Hippowdon,,
|
|
||||||
267,Sandile,,
|
|
||||||
268,Krokorok,,
|
|
||||||
269,Krookodile,,
|
|
||||||
270,Silicobra,,
|
|
||||||
271,Sandaconda,,
|
|
||||||
272,Mudbray,,
|
|
||||||
273,Mudsdale,,
|
|
||||||
274,Larvesta,,
|
|
||||||
275,Volcarona,,
|
|
||||||
276,Bagon,,
|
|
||||||
277,Shelgon,,
|
|
||||||
278,Salamence,,
|
|
||||||
279,Tinkatink,,
|
|
||||||
280,Tinkatuff,,
|
|
||||||
281,Tinkaton,,
|
|
||||||
282,Hatenna,,
|
|
||||||
283,Hattrem,,
|
|
||||||
284,Hatterene,,
|
|
||||||
285,Impidimp,,
|
|
||||||
286,Morgrem,,
|
|
||||||
287,Grimmsnarl,,
|
|
||||||
288,Wiglett,,
|
|
||||||
289,Wugtrio,,
|
|
||||||
290,Bombirdier,,
|
|
||||||
291,Finizen,,
|
|
||||||
292,Palafin,,
|
|
||||||
293,Varoom,,
|
|
||||||
294,Revavroom,,
|
|
||||||
295,Cyclizar,,
|
|
||||||
296,Orthworm,,
|
|
||||||
297,Sableye,,
|
|
||||||
298,Shuppet,,
|
|
||||||
299,Banette,,
|
|
||||||
300,Falinks,,
|
|
||||||
301,Hawlucha,,
|
|
||||||
302,Spiritomb,,
|
|
||||||
303,Noibat,,
|
|
||||||
304,Noivern,,
|
|
||||||
305,Dreepy,,
|
|
||||||
306,Drakloak,,
|
|
||||||
307,Dragapult,,
|
|
||||||
308,Glimmet,,
|
|
||||||
309,Glimmora,,
|
|
||||||
310,Rotom,,
|
|
||||||
311,Greavard,,
|
|
||||||
312,Houndstone,,
|
|
||||||
313,Oranguru,,
|
|
||||||
314,Passimian,,
|
|
||||||
315,Komala,,
|
|
||||||
316,Larvitar,,
|
|
||||||
317,Pupitar,,
|
|
||||||
318,Tyranitar,,
|
|
||||||
319,Stonjourner,,
|
|
||||||
320,Eiscue,,
|
|
||||||
321,Pincurchin,,
|
|
||||||
322,Sandygast,,
|
|
||||||
323,Palossand,,
|
|
||||||
324,Slowpoke,,
|
|
||||||
325,Slowbro,,
|
|
||||||
326,Slowking,,
|
|
||||||
327,Shellos,,
|
|
||||||
328,Gastrodon,,
|
|
||||||
329,Shellder,,
|
|
||||||
330,Cloyster,,
|
|
||||||
331,Qwilfish,,
|
|
||||||
332,Luvdisc,,
|
|
||||||
333,Finneon,,
|
|
||||||
334,Lumineon,,
|
|
||||||
335,Bruxish,,
|
|
||||||
336,Alomomola,,
|
|
||||||
337,Skrelp,,
|
|
||||||
338,Dragalge,,
|
|
||||||
339,Clauncher,,
|
|
||||||
340,Clawitzer,,
|
|
||||||
341,Tynamo,,
|
|
||||||
342,Eelektrik,,
|
|
||||||
343,Eelektross,,
|
|
||||||
344,Mareanie,,
|
|
||||||
345,Toxapex,,
|
|
||||||
346,Flamigo,,
|
|
||||||
347,Dratini,,
|
|
||||||
348,Dragonair,,
|
|
||||||
349,Dragonite,,
|
|
||||||
350,Snom,,
|
|
||||||
351,Frosmoth,,
|
|
||||||
352,Snover,,
|
|
||||||
353,Abomasnow,,
|
|
||||||
354,Delibird,,
|
|
||||||
355,Cubchoo,,
|
|
||||||
356,Beartic,,
|
|
||||||
357,Snorunt,,
|
|
||||||
358,Glalie,,
|
|
||||||
359,Froslass,,
|
|
||||||
360,Cryogonal,,
|
|
||||||
361,Cetoddle,,
|
|
||||||
362,Cetitan,,
|
|
||||||
363,Bergmite,,
|
|
||||||
364,Avalugg,,
|
|
||||||
365,Rufflet,,
|
|
||||||
366,Braviary,,
|
|
||||||
367,Pawniard,,
|
|
||||||
368,Bisharp,,
|
|
||||||
369,Kingambit,,
|
|
||||||
370,Deino,,
|
|
||||||
371,Zweilous,,
|
|
||||||
372,Hydreigon,,
|
|
||||||
373,Veluza,,
|
|
||||||
374,Dondozo,,
|
|
||||||
375,Tatsugiri,,
|
|
||||||
376,Great Tusk,,
|
|
||||||
377,Scream Tail,,
|
|
||||||
378,Brute Bonnet,,
|
|
||||||
379,Flutter Mane,,
|
|
||||||
380,Slither Wing,,
|
|
||||||
381,Sandy Shocks,,
|
|
||||||
382,Iron Treads,,
|
|
||||||
383,Iron Bundle,,
|
|
||||||
384,Iron Hands,,
|
|
||||||
385,Iron Jugulis,,
|
|
||||||
386,Iron Moth,,
|
|
||||||
387,Iron Thorns,,
|
|
||||||
388,Frigibax,,
|
|
||||||
389,Arctibax,,
|
|
||||||
390,Baxcalibur,,
|
|
||||||
391,Gimmighoul,,
|
|
||||||
392,Gholdengo,,
|
|
||||||
393,Wo-Chien,,
|
|
||||||
394,Chien-Pao,,
|
|
||||||
395,Ting-Lu,,
|
|
||||||
396,Chi-Yu,,
|
|
||||||
397,Roaring Moon,,
|
|
||||||
398,Iron Valiant,,
|
|
||||||
399,Koraidon,,
|
|
||||||
400,Miraidon,,
|
|
||||||
|
@@ -1,131 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Pikipek,,
|
|
||||||
2,Trumbeak,,
|
|
||||||
3,Toucannon,,
|
|
||||||
4,Yungoos,,
|
|
||||||
5,Gumshoos,,
|
|
||||||
6,Rattata,,
|
|
||||||
7,Raticate,,
|
|
||||||
8,Caterpie,,
|
|
||||||
9,Metapod,,
|
|
||||||
10,Butterfree,,
|
|
||||||
11,Grubbin,,
|
|
||||||
12,Charjabug,,
|
|
||||||
13,Vikavolt,,
|
|
||||||
14,Bonsly,,
|
|
||||||
15,Sudowoodo,,
|
|
||||||
16,Happiny,,
|
|
||||||
17,Chansey,,
|
|
||||||
18,Blissey,,
|
|
||||||
19,Wingull,,
|
|
||||||
20,Pelipper,,
|
|
||||||
21,Crabrawler,,
|
|
||||||
22,Crabominable,,
|
|
||||||
23,Gastly,,
|
|
||||||
24,Haunter,,
|
|
||||||
25,Gengar,,
|
|
||||||
26,Zubat,,
|
|
||||||
27,Golbat,,
|
|
||||||
28,Crobat,,
|
|
||||||
29,Diglett,,
|
|
||||||
30,Dugtrio,,
|
|
||||||
31,Oricorio,,
|
|
||||||
32,Psyduck,,
|
|
||||||
33,Golduck,,
|
|
||||||
34,Magikarp,,
|
|
||||||
35,Gyarados,,
|
|
||||||
36,Barboach,,
|
|
||||||
37,Whiscash,,
|
|
||||||
38,Tentacool,,
|
|
||||||
39,Tentacruel,,
|
|
||||||
40,Finneon,,
|
|
||||||
41,Lumineon,,
|
|
||||||
42,Wishiwashi,,
|
|
||||||
43,Luvdisc,,
|
|
||||||
44,Corsola,,
|
|
||||||
45,Mareanie,,
|
|
||||||
46,Toxapex,,
|
|
||||||
47,Lillipup,,
|
|
||||||
48,Herdier,,
|
|
||||||
49,Stoutland,,
|
|
||||||
50,Eevee,,
|
|
||||||
51,Vaporeon,,
|
|
||||||
52,Jolteon,,
|
|
||||||
53,Flareon,,
|
|
||||||
54,Espeon,,
|
|
||||||
55,Umbreon,,
|
|
||||||
56,Leafeon,,
|
|
||||||
57,Glaceon,,
|
|
||||||
58,Sylveon,,
|
|
||||||
59,Mudbray,,
|
|
||||||
60,Mudsdale,,
|
|
||||||
61,Igglybuff,,
|
|
||||||
62,Jigglypuff,,
|
|
||||||
63,Wigglytuff,,
|
|
||||||
64,Tauros,,
|
|
||||||
65,Miltank,,
|
|
||||||
66,Surskit,,
|
|
||||||
67,Masquerain,,
|
|
||||||
68,Dewpider,,
|
|
||||||
69,Araquanid,,
|
|
||||||
70,Fomantis,,
|
|
||||||
71,Lurantis,,
|
|
||||||
72,Morelull,,
|
|
||||||
73,Shiinotic,,
|
|
||||||
74,Paras,,
|
|
||||||
75,Parasect,,
|
|
||||||
76,Poliwag,,
|
|
||||||
77,Poliwhirl,,
|
|
||||||
78,Poliwrath,,
|
|
||||||
79,Politoed,,
|
|
||||||
80,Goldeen,,
|
|
||||||
81,Seaking,,
|
|
||||||
82,Feebas,,
|
|
||||||
83,Milotic,,
|
|
||||||
84,Alomomola,,
|
|
||||||
85,Fletchling,,
|
|
||||||
86,Fletchinder,,
|
|
||||||
87,Talonflame,,
|
|
||||||
88,Salandit,,
|
|
||||||
89,Salazzle,,
|
|
||||||
90,Cubone,,
|
|
||||||
91,Marowak,,
|
|
||||||
92,Kangaskhan,,
|
|
||||||
93,Magby,,
|
|
||||||
94,Magmar,,
|
|
||||||
95,Magmortar,,
|
|
||||||
96,Stufful,,
|
|
||||||
97,Bewear,,
|
|
||||||
98,Bounsweet,,
|
|
||||||
99,Steenee,,
|
|
||||||
100,Tsareena,,
|
|
||||||
101,Comfey,,
|
|
||||||
102,Pinsir,,
|
|
||||||
103,Oranguru,,
|
|
||||||
104,Passimian,,
|
|
||||||
105,Goomy,,
|
|
||||||
106,Sliggoo,,
|
|
||||||
107,Goodra,,
|
|
||||||
108,Castform,,
|
|
||||||
109,Wimpod,,
|
|
||||||
110,Golisopod,,
|
|
||||||
111,Staryu,,
|
|
||||||
112,Starmie,,
|
|
||||||
113,Sandygast,,
|
|
||||||
114,Palossand,,
|
|
||||||
115,Cranidos,,
|
|
||||||
116,Rampardos,,
|
|
||||||
117,Shieldon,,
|
|
||||||
118,Bastiodon,,
|
|
||||||
119,Archen,,
|
|
||||||
120,Archeops,,
|
|
||||||
121,Tirtouga,,
|
|
||||||
122,Carracosta,,
|
|
||||||
123,Phantump,,
|
|
||||||
124,Trevenant,,
|
|
||||||
125,Nosepass,,
|
|
||||||
126,Probopass,,
|
|
||||||
127,Pyukumuku,,
|
|
||||||
128,Chinchou,,
|
|
||||||
129,Lanturn,,
|
|
||||||
130,Tapu Lele,,
|
|
||||||
|
@@ -1,303 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Rowlet,,
|
|
||||||
2,Dartrix,,
|
|
||||||
3,Decidueye,,
|
|
||||||
4,Litten,,
|
|
||||||
5,Torracat,,
|
|
||||||
6,Incineroar,,
|
|
||||||
7,Popplio,,
|
|
||||||
8,Brionne,,
|
|
||||||
9,Primarina,,
|
|
||||||
10,Pikipek,,
|
|
||||||
11,Trumbeak,,
|
|
||||||
12,Toucannon,,
|
|
||||||
13,Yungoos,,
|
|
||||||
14,Gumshoos,,
|
|
||||||
15,Rattata,,
|
|
||||||
16,Raticate,,
|
|
||||||
17,Caterpie,,
|
|
||||||
18,Metapod,,
|
|
||||||
19,Butterfree,,
|
|
||||||
20,Ledyba,,
|
|
||||||
21,Ledian,,
|
|
||||||
22,Spinarak,,
|
|
||||||
23,Ariados,,
|
|
||||||
24,Pichu,,
|
|
||||||
25,Pikachu,,
|
|
||||||
26,Raichu,,
|
|
||||||
27,Grubbin,,
|
|
||||||
28,Charjabug,,
|
|
||||||
29,Vikavolt,,
|
|
||||||
30,Bonsly,,
|
|
||||||
31,Sudowoodo,,
|
|
||||||
32,Happiny,,
|
|
||||||
33,Chansey,,
|
|
||||||
34,Blissey,,
|
|
||||||
35,Munchlax,,
|
|
||||||
36,Snorlax,,
|
|
||||||
37,Slowpoke,,
|
|
||||||
38,Slowbro,,
|
|
||||||
39,Slowking,,
|
|
||||||
40,Wingull,,
|
|
||||||
41,Pelipper,,
|
|
||||||
42,Abra,,
|
|
||||||
43,Kadabra,,
|
|
||||||
44,Alakazam,,
|
|
||||||
45,Meowth,,
|
|
||||||
46,Persian,,
|
|
||||||
47,Magnemite,,
|
|
||||||
48,Magneton,,
|
|
||||||
49,Magnezone,,
|
|
||||||
50,Grimer,,
|
|
||||||
51,Muk,,
|
|
||||||
52,Growlithe,,
|
|
||||||
53,Arcanine,,
|
|
||||||
54,Drowzee,,
|
|
||||||
55,Hypno,,
|
|
||||||
56,Makuhita,,
|
|
||||||
57,Hariyama,,
|
|
||||||
58,Smeargle,,
|
|
||||||
59,Crabrawler,,
|
|
||||||
60,Crabominable,,
|
|
||||||
61,Gastly,,
|
|
||||||
62,Haunter,,
|
|
||||||
63,Gengar,,
|
|
||||||
64,Drifloon,,
|
|
||||||
65,Drifblim,,
|
|
||||||
66,Misdreavus,,
|
|
||||||
67,Mismagius,,
|
|
||||||
68,Zubat,,
|
|
||||||
69,Golbat,,
|
|
||||||
70,Crobat,,
|
|
||||||
71,Diglett,,
|
|
||||||
72,Dugtrio,,
|
|
||||||
73,Spearow,,
|
|
||||||
74,Fearow,,
|
|
||||||
75,Rufflet,,
|
|
||||||
76,Braviary,,
|
|
||||||
77,Vullaby,,
|
|
||||||
78,Mandibuzz,,
|
|
||||||
79,Mankey,,
|
|
||||||
80,Primeape,,
|
|
||||||
81,Delibird,,
|
|
||||||
82,Oricorio,,
|
|
||||||
83,Cutiefly,,
|
|
||||||
84,Ribombee,,
|
|
||||||
85,Petilil,,
|
|
||||||
86,Lilligant,,
|
|
||||||
87,Cottonee,,
|
|
||||||
88,Whimsicott,,
|
|
||||||
89,Psyduck,,
|
|
||||||
90,Golduck,,
|
|
||||||
91,Magikarp,,
|
|
||||||
92,Gyarados,,
|
|
||||||
93,Barboach,,
|
|
||||||
94,Whiscash,,
|
|
||||||
95,Machop,,
|
|
||||||
96,Machoke,,
|
|
||||||
97,Machamp,,
|
|
||||||
98,Roggenrola,,
|
|
||||||
99,Boldore,,
|
|
||||||
100,Gigalith,,
|
|
||||||
101,Carbink,,
|
|
||||||
102,Sableye,,
|
|
||||||
103,Rockruff,,
|
|
||||||
104,Lycanroc,,
|
|
||||||
105,Spinda,,
|
|
||||||
106,Tentacool,,
|
|
||||||
107,Tentacruel,,
|
|
||||||
108,Finneon,,
|
|
||||||
109,Lumineon,,
|
|
||||||
110,Wishiwashi,,
|
|
||||||
111,Luvdisc,,
|
|
||||||
112,Corsola,,
|
|
||||||
113,Mareanie,,
|
|
||||||
114,Toxapex,,
|
|
||||||
115,Shellder,,
|
|
||||||
116,Cloyster,,
|
|
||||||
117,Bagon,,
|
|
||||||
118,Shelgon,,
|
|
||||||
119,Salamence,,
|
|
||||||
120,Lillipup,,
|
|
||||||
121,Herdier,,
|
|
||||||
122,Stoutland,,
|
|
||||||
123,Eevee,,
|
|
||||||
124,Vaporeon,,
|
|
||||||
125,Jolteon,,
|
|
||||||
126,Flareon,,
|
|
||||||
127,Espeon,,
|
|
||||||
128,Umbreon,,
|
|
||||||
129,Leafeon,,
|
|
||||||
130,Glaceon,,
|
|
||||||
131,Sylveon,,
|
|
||||||
132,Mudbray,,
|
|
||||||
133,Mudsdale,,
|
|
||||||
134,Igglybuff,,
|
|
||||||
135,Jigglypuff,,
|
|
||||||
136,Wigglytuff,,
|
|
||||||
137,Tauros,,
|
|
||||||
138,Miltank,,
|
|
||||||
139,Surskit,,
|
|
||||||
140,Masquerain,,
|
|
||||||
141,Dewpider,,
|
|
||||||
142,Araquanid,,
|
|
||||||
143,Fomantis,,
|
|
||||||
144,Lurantis,,
|
|
||||||
145,Morelull,,
|
|
||||||
146,Shiinotic,,
|
|
||||||
147,Paras,,
|
|
||||||
148,Parasect,,
|
|
||||||
149,Poliwag,,
|
|
||||||
150,Poliwhirl,,
|
|
||||||
151,Poliwrath,,
|
|
||||||
152,Politoed,,
|
|
||||||
153,Goldeen,,
|
|
||||||
154,Seaking,,
|
|
||||||
155,Feebas,,
|
|
||||||
156,Milotic,,
|
|
||||||
157,Alomomola,,
|
|
||||||
158,Fletchling,,
|
|
||||||
159,Fletchinder,,
|
|
||||||
160,Talonflame,,
|
|
||||||
161,Salandit,,
|
|
||||||
162,Salazzle,,
|
|
||||||
163,Cubone,,
|
|
||||||
164,Marowak,,
|
|
||||||
165,Kangaskhan,,
|
|
||||||
166,Magby,,
|
|
||||||
167,Magmar,,
|
|
||||||
168,Magmortar,,
|
|
||||||
169,Stufful,,
|
|
||||||
170,Bewear,,
|
|
||||||
171,Bounsweet,,
|
|
||||||
172,Steenee,,
|
|
||||||
173,Tsareena,,
|
|
||||||
174,Comfey,,
|
|
||||||
175,Pinsir,,
|
|
||||||
176,Oranguru,,
|
|
||||||
177,Passimian,,
|
|
||||||
178,Goomy,,
|
|
||||||
179,Sliggoo,,
|
|
||||||
180,Goodra,,
|
|
||||||
181,Castform,,
|
|
||||||
182,Wimpod,,
|
|
||||||
183,Golisopod,,
|
|
||||||
184,Staryu,,
|
|
||||||
185,Starmie,,
|
|
||||||
186,Sandygast,,
|
|
||||||
187,Palossand,,
|
|
||||||
188,Cranidos,,
|
|
||||||
189,Rampardos,,
|
|
||||||
190,Shieldon,,
|
|
||||||
191,Bastiodon,,
|
|
||||||
192,Archen,,
|
|
||||||
193,Archeops,,
|
|
||||||
194,Tirtouga,,
|
|
||||||
195,Carracosta,,
|
|
||||||
196,Phantump,,
|
|
||||||
197,Trevenant,,
|
|
||||||
198,Nosepass,,
|
|
||||||
199,Probopass,,
|
|
||||||
200,Pyukumuku,,
|
|
||||||
201,Chinchou,,
|
|
||||||
202,Lanturn,,
|
|
||||||
203,Type: Null,,
|
|
||||||
204,Silvally,,
|
|
||||||
205,Zygarde,,
|
|
||||||
206,Trubbish,,
|
|
||||||
207,Garbodor,,
|
|
||||||
208,Skarmory,,
|
|
||||||
209,Ditto,,
|
|
||||||
210,Cleffa,,
|
|
||||||
211,Clefairy,,
|
|
||||||
212,Clefable,,
|
|
||||||
213,Minior,,
|
|
||||||
214,Beldum,,
|
|
||||||
215,Metang,,
|
|
||||||
216,Metagross,,
|
|
||||||
217,Porygon,,
|
|
||||||
218,Porygon2,,
|
|
||||||
219,Porygon-Z,,
|
|
||||||
220,Pancham,,
|
|
||||||
221,Pangoro,,
|
|
||||||
222,Komala,,
|
|
||||||
223,Torkoal,,
|
|
||||||
224,Turtonator,,
|
|
||||||
225,Togedemaru,,
|
|
||||||
226,Elekid,,
|
|
||||||
227,Electabuzz,,
|
|
||||||
228,Electivire,,
|
|
||||||
229,Geodude,,
|
|
||||||
230,Graveler,,
|
|
||||||
231,Golem,,
|
|
||||||
232,Sandile,,
|
|
||||||
233,Krokorok,,
|
|
||||||
234,Krookodile,,
|
|
||||||
235,Trapinch,,
|
|
||||||
236,Vibrava,,
|
|
||||||
237,Flygon,,
|
|
||||||
238,Gible,,
|
|
||||||
239,Gabite,,
|
|
||||||
240,Garchomp,,
|
|
||||||
241,Klefki,,
|
|
||||||
242,Mimikyu,,
|
|
||||||
243,Bruxish,,
|
|
||||||
244,Drampa,,
|
|
||||||
245,Absol,,
|
|
||||||
246,Snorunt,,
|
|
||||||
247,Glalie,,
|
|
||||||
248,Froslass,,
|
|
||||||
249,Sneasel,,
|
|
||||||
250,Weavile,,
|
|
||||||
251,Sandshrew,,
|
|
||||||
252,Sandslash,,
|
|
||||||
253,Vulpix,,
|
|
||||||
254,Ninetales,,
|
|
||||||
255,Vanillite,,
|
|
||||||
256,Vanillish,,
|
|
||||||
257,Vanilluxe,,
|
|
||||||
258,Snubbull,,
|
|
||||||
259,Granbull,,
|
|
||||||
260,Shellos,,
|
|
||||||
261,Gastrodon,,
|
|
||||||
262,Relicanth,,
|
|
||||||
263,Dhelmise,,
|
|
||||||
264,Carvanha,,
|
|
||||||
265,Sharpedo,,
|
|
||||||
266,Wailmer,,
|
|
||||||
267,Wailord,,
|
|
||||||
268,Lapras,,
|
|
||||||
269,Exeggcute,,
|
|
||||||
270,Exeggutor,,
|
|
||||||
271,Jangmo-o,,
|
|
||||||
272,Hakamo-o,,
|
|
||||||
273,Kommo-o,,
|
|
||||||
274,Emolga,,
|
|
||||||
275,Scyther,,
|
|
||||||
276,Scizor,,
|
|
||||||
277,Murkrow,,
|
|
||||||
278,Honchkrow,,
|
|
||||||
279,Riolu,,
|
|
||||||
280,Lucario,,
|
|
||||||
281,Dratini,,
|
|
||||||
282,Dragonair,,
|
|
||||||
283,Dragonite,,
|
|
||||||
284,Aerodactyl,,
|
|
||||||
285,Tapu Koko,,
|
|
||||||
286,Tapu Lele,,
|
|
||||||
287,Tapu Bulu,,
|
|
||||||
288,Tapu Fini,,
|
|
||||||
289,Cosmog,,
|
|
||||||
290,Cosmoem,,
|
|
||||||
291,Solgaleo,,
|
|
||||||
292,Lunala,,
|
|
||||||
293,Nihilego,,
|
|
||||||
294,Buzzwole,,
|
|
||||||
295,Pheromosa,,
|
|
||||||
296,Xurkitree,,
|
|
||||||
297,Celesteela,,
|
|
||||||
298,Kartana,,
|
|
||||||
299,Guzzlord,,
|
|
||||||
300,Necrozma,,
|
|
||||||
301,Magearna,,
|
|
||||||
302,Marshadow,,
|
|
||||||
|
@@ -1,121 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Rowlet,,
|
|
||||||
2,Dartrix,,
|
|
||||||
3,Decidueye,,
|
|
||||||
4,Litten,,
|
|
||||||
5,Torracat,,
|
|
||||||
6,Incineroar,,
|
|
||||||
7,Popplio,,
|
|
||||||
8,Brionne,,
|
|
||||||
9,Primarina,,
|
|
||||||
10,Pikipek,,
|
|
||||||
11,Trumbeak,,
|
|
||||||
12,Toucannon,,
|
|
||||||
13,Yungoos,,
|
|
||||||
14,Gumshoos,,
|
|
||||||
15,Rattata,,
|
|
||||||
16,Raticate,,
|
|
||||||
17,Caterpie,,
|
|
||||||
18,Metapod,,
|
|
||||||
19,Butterfree,,
|
|
||||||
20,Ledyba,,
|
|
||||||
21,Ledian,,
|
|
||||||
22,Spinarak,,
|
|
||||||
23,Ariados,,
|
|
||||||
24,Pichu,,
|
|
||||||
25,Pikachu,,
|
|
||||||
26,Raichu,,
|
|
||||||
27,Grubbin,,
|
|
||||||
28,Charjabug,,
|
|
||||||
29,Vikavolt,,
|
|
||||||
30,Bonsly,,
|
|
||||||
31,Sudowoodo,,
|
|
||||||
32,Happiny,,
|
|
||||||
33,Chansey,,
|
|
||||||
34,Blissey,,
|
|
||||||
35,Munchlax,,
|
|
||||||
36,Snorlax,,
|
|
||||||
37,Slowpoke,,
|
|
||||||
38,Slowbro,,
|
|
||||||
39,Slowking,,
|
|
||||||
40,Wingull,,
|
|
||||||
41,Pelipper,,
|
|
||||||
42,Abra,,
|
|
||||||
43,Kadabra,,
|
|
||||||
44,Alakazam,,
|
|
||||||
45,Meowth,,
|
|
||||||
46,Persian,,
|
|
||||||
47,Magnemite,,
|
|
||||||
48,Magneton,,
|
|
||||||
49,Magnezone,,
|
|
||||||
50,Grimer,,
|
|
||||||
51,Muk,,
|
|
||||||
52,Growlithe,,
|
|
||||||
53,Arcanine,,
|
|
||||||
54,Drowzee,,
|
|
||||||
55,Hypno,,
|
|
||||||
56,Makuhita,,
|
|
||||||
57,Hariyama,,
|
|
||||||
58,Smeargle,,
|
|
||||||
59,Crabrawler,,
|
|
||||||
60,Crabominable,,
|
|
||||||
61,Gastly,,
|
|
||||||
62,Haunter,,
|
|
||||||
63,Gengar,,
|
|
||||||
64,Drifloon,,
|
|
||||||
65,Drifblim,,
|
|
||||||
66,Misdreavus,,
|
|
||||||
67,Mismagius,,
|
|
||||||
68,Zubat,,
|
|
||||||
69,Golbat,,
|
|
||||||
70,Crobat,,
|
|
||||||
71,Diglett,,
|
|
||||||
72,Dugtrio,,
|
|
||||||
73,Spearow,,
|
|
||||||
74,Fearow,,
|
|
||||||
75,Rufflet,,
|
|
||||||
76,Braviary,,
|
|
||||||
77,Vullaby,,
|
|
||||||
78,Mandibuzz,,
|
|
||||||
79,Mankey,,
|
|
||||||
80,Primeape,,
|
|
||||||
81,Delibird,,
|
|
||||||
82,Oricorio,,
|
|
||||||
83,Cutiefly,,
|
|
||||||
84,Ribombee,,
|
|
||||||
85,Petilil,,
|
|
||||||
86,Lilligant,,
|
|
||||||
87,Cottonee,,
|
|
||||||
88,Whimsicott,,
|
|
||||||
89,Psyduck,,
|
|
||||||
90,Golduck,,
|
|
||||||
91,Magikarp,,
|
|
||||||
92,Gyarados,,
|
|
||||||
93,Barboach,,
|
|
||||||
94,Whiscash,,
|
|
||||||
95,Machop,,
|
|
||||||
96,Machoke,,
|
|
||||||
97,Machamp,,
|
|
||||||
98,Roggenrola,,
|
|
||||||
99,Boldore,,
|
|
||||||
100,Gigalith,,
|
|
||||||
101,Carbink,,
|
|
||||||
102,Sableye,,
|
|
||||||
103,Rockruff,,
|
|
||||||
104,Lycanroc,,
|
|
||||||
105,Spinda,,
|
|
||||||
106,Tentacool,,
|
|
||||||
107,Tentacruel,,
|
|
||||||
108,Finneon,,
|
|
||||||
109,Lumineon,,
|
|
||||||
110,Wishiwashi,,
|
|
||||||
111,Luvdisc,,
|
|
||||||
112,Corsola,,
|
|
||||||
113,Mareanie,,
|
|
||||||
114,Toxapex,,
|
|
||||||
115,Shellder,,
|
|
||||||
116,Cloyster,,
|
|
||||||
117,Bagon,,
|
|
||||||
118,Shelgon,,
|
|
||||||
119,Salamence,,
|
|
||||||
120,Tapu Koko,,
|
|
||||||
|
@@ -1,101 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Pikipek,,
|
|
||||||
2,Trumbeak,,
|
|
||||||
3,Toucannon,,
|
|
||||||
4,Yungoos,,
|
|
||||||
5,Gumshoos,,
|
|
||||||
6,Rattata,,
|
|
||||||
7,Raticate,,
|
|
||||||
8,Happiny,,
|
|
||||||
9,Chansey,,
|
|
||||||
10,Blissey,,
|
|
||||||
11,Wingull,,
|
|
||||||
12,Pelipper,,
|
|
||||||
13,Drowzee,,
|
|
||||||
14,Hypno,,
|
|
||||||
15,Makuhita,,
|
|
||||||
16,Hariyama,,
|
|
||||||
17,Crabrawler,,
|
|
||||||
18,Crabominable,,
|
|
||||||
19,Zubat,,
|
|
||||||
20,Golbat,,
|
|
||||||
21,Crobat,,
|
|
||||||
22,Diglett,,
|
|
||||||
23,Dugtrio,,
|
|
||||||
24,Spearow,,
|
|
||||||
25,Fearow,,
|
|
||||||
26,Rufflet,,
|
|
||||||
27,Braviary,,
|
|
||||||
28,Vullaby,,
|
|
||||||
29,Mandibuzz,,
|
|
||||||
30,Mankey,,
|
|
||||||
31,Primeape,,
|
|
||||||
32,Oricorio,,
|
|
||||||
33,Cutiefly,,
|
|
||||||
34,Ribombee,,
|
|
||||||
35,Petilil,,
|
|
||||||
36,Lilligant,,
|
|
||||||
37,Cottonee,,
|
|
||||||
38,Whimsicott,,
|
|
||||||
39,Psyduck,,
|
|
||||||
40,Golduck,,
|
|
||||||
41,Magikarp,,
|
|
||||||
42,Gyarados,,
|
|
||||||
43,Barboach,,
|
|
||||||
44,Whiscash,,
|
|
||||||
45,Machop,,
|
|
||||||
46,Machoke,,
|
|
||||||
47,Machamp,,
|
|
||||||
48,Roggenrola,,
|
|
||||||
49,Boldore,,
|
|
||||||
50,Gigalith,,
|
|
||||||
51,Carbink,,
|
|
||||||
52,Sableye,,
|
|
||||||
53,Rockruff,,
|
|
||||||
54,Lycanroc,,
|
|
||||||
55,Tentacool,,
|
|
||||||
56,Tentacruel,,
|
|
||||||
57,Finneon,,
|
|
||||||
58,Lumineon,,
|
|
||||||
59,Mudbray,,
|
|
||||||
60,Mudsdale,,
|
|
||||||
61,Tauros,,
|
|
||||||
62,Miltank,,
|
|
||||||
63,Stufful,,
|
|
||||||
64,Bewear,,
|
|
||||||
65,Pinsir,,
|
|
||||||
66,Goomy,,
|
|
||||||
67,Sliggoo,,
|
|
||||||
68,Goodra,,
|
|
||||||
69,Castform,,
|
|
||||||
70,Wimpod,,
|
|
||||||
71,Golisopod,,
|
|
||||||
72,Skarmory,,
|
|
||||||
73,Snubbull,,
|
|
||||||
74,Granbull,,
|
|
||||||
75,Shellos,,
|
|
||||||
76,Gastrodon,,
|
|
||||||
77,Relicanth,,
|
|
||||||
78,Dhelmise,,
|
|
||||||
79,Carvanha,,
|
|
||||||
80,Sharpedo,,
|
|
||||||
81,Wailmer,,
|
|
||||||
82,Wailord,,
|
|
||||||
83,Lapras,,
|
|
||||||
84,Exeggcute,,
|
|
||||||
85,Exeggutor,,
|
|
||||||
86,Jangmo-o,,
|
|
||||||
87,Hakamo-o,,
|
|
||||||
88,Kommo-o,,
|
|
||||||
89,Emolga,,
|
|
||||||
90,Scyther,,
|
|
||||||
91,Scizor,,
|
|
||||||
92,Murkrow,,
|
|
||||||
93,Honchkrow,,
|
|
||||||
94,Riolu,,
|
|
||||||
95,Lucario,,
|
|
||||||
96,Dratini,,
|
|
||||||
97,Dragonair,,
|
|
||||||
98,Dragonite,,
|
|
||||||
99,Aerodactyl,,
|
|
||||||
100,Tapu Fini,,
|
|
||||||
|
@@ -1,131 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Pikipek,,
|
|
||||||
2,Trumbeak,,
|
|
||||||
3,Toucannon,,
|
|
||||||
4,Yungoos,,
|
|
||||||
5,Gumshoos,,
|
|
||||||
6,Rattata,,
|
|
||||||
7,Raticate,,
|
|
||||||
8,Ledyba,,
|
|
||||||
9,Ledian,,
|
|
||||||
10,Spinarak,,
|
|
||||||
11,Ariados,,
|
|
||||||
12,Grubbin,,
|
|
||||||
13,Charjabug,,
|
|
||||||
14,Vikavolt,,
|
|
||||||
15,Happiny,,
|
|
||||||
16,Chansey,,
|
|
||||||
17,Blissey,,
|
|
||||||
18,Slowpoke,,
|
|
||||||
19,Slowbro,,
|
|
||||||
20,Slowking,,
|
|
||||||
21,Wingull,,
|
|
||||||
22,Pelipper,,
|
|
||||||
23,Meowth,,
|
|
||||||
24,Persian,,
|
|
||||||
25,Magnemite,,
|
|
||||||
26,Magneton,,
|
|
||||||
27,Magnezone,,
|
|
||||||
28,Grimer,,
|
|
||||||
29,Muk,,
|
|
||||||
30,Crabrawler,,
|
|
||||||
31,Crabominable,,
|
|
||||||
32,Gastly,,
|
|
||||||
33,Haunter,,
|
|
||||||
34,Gengar,,
|
|
||||||
35,Zubat,,
|
|
||||||
36,Golbat,,
|
|
||||||
37,Crobat,,
|
|
||||||
38,Diglett,,
|
|
||||||
39,Dugtrio,,
|
|
||||||
40,Spearow,,
|
|
||||||
41,Fearow,,
|
|
||||||
42,Oricorio,,
|
|
||||||
43,Cutiefly,,
|
|
||||||
44,Ribombee,,
|
|
||||||
45,Petilil,,
|
|
||||||
46,Lilligant,,
|
|
||||||
47,Cottonee,,
|
|
||||||
48,Whimsicott,,
|
|
||||||
49,Psyduck,,
|
|
||||||
50,Golduck,,
|
|
||||||
51,Magikarp,,
|
|
||||||
52,Gyarados,,
|
|
||||||
53,Tentacool,,
|
|
||||||
54,Tentacruel,,
|
|
||||||
55,Finneon,,
|
|
||||||
56,Lumineon,,
|
|
||||||
57,Wishiwashi,,
|
|
||||||
58,Mudbray,,
|
|
||||||
59,Mudsdale,,
|
|
||||||
60,Surskit,,
|
|
||||||
61,Masquerain,,
|
|
||||||
62,Dewpider,,
|
|
||||||
63,Araquanid,,
|
|
||||||
64,Morelull,,
|
|
||||||
65,Shiinotic,,
|
|
||||||
66,Paras,,
|
|
||||||
67,Parasect,,
|
|
||||||
68,Poliwag,,
|
|
||||||
69,Poliwhirl,,
|
|
||||||
70,Poliwrath,,
|
|
||||||
71,Politoed,,
|
|
||||||
72,Goldeen,,
|
|
||||||
73,Seaking,,
|
|
||||||
74,Goomy,,
|
|
||||||
75,Sliggoo,,
|
|
||||||
76,Goodra,,
|
|
||||||
77,Castform,,
|
|
||||||
78,Trubbish,,
|
|
||||||
79,Garbodor,,
|
|
||||||
80,Skarmory,,
|
|
||||||
81,Ditto,,
|
|
||||||
82,Cleffa,,
|
|
||||||
83,Clefairy,,
|
|
||||||
84,Clefable,,
|
|
||||||
85,Minior,,
|
|
||||||
86,Beldum,,
|
|
||||||
87,Metang,,
|
|
||||||
88,Metagross,,
|
|
||||||
89,Porygon,,
|
|
||||||
90,Porygon2,,
|
|
||||||
91,Porygon-Z,,
|
|
||||||
92,Pancham,,
|
|
||||||
93,Pangoro,,
|
|
||||||
94,Komala,,
|
|
||||||
95,Torkoal,,
|
|
||||||
96,Turtonator,,
|
|
||||||
97,Togedemaru,,
|
|
||||||
98,Elekid,,
|
|
||||||
99,Electabuzz,,
|
|
||||||
100,Electivire,,
|
|
||||||
101,Geodude,,
|
|
||||||
102,Graveler,,
|
|
||||||
103,Golem,,
|
|
||||||
104,Sandile,,
|
|
||||||
105,Krokorok,,
|
|
||||||
106,Krookodile,,
|
|
||||||
107,Trapinch,,
|
|
||||||
108,Vibrava,,
|
|
||||||
109,Flygon,,
|
|
||||||
110,Gible,,
|
|
||||||
111,Gabite,,
|
|
||||||
112,Garchomp,,
|
|
||||||
113,Klefki,,
|
|
||||||
114,Mimikyu,,
|
|
||||||
115,Bruxish,,
|
|
||||||
116,Drampa,,
|
|
||||||
117,Absol,,
|
|
||||||
118,Snorunt,,
|
|
||||||
119,Glalie,,
|
|
||||||
120,Froslass,,
|
|
||||||
121,Sneasel,,
|
|
||||||
122,Weavile,,
|
|
||||||
123,Sandshrew,,
|
|
||||||
124,Sandslash,,
|
|
||||||
125,Vulpix,,
|
|
||||||
126,Ninetales,,
|
|
||||||
127,Vanillite,,
|
|
||||||
128,Vanillish,,
|
|
||||||
129,Vanilluxe,,
|
|
||||||
130,Tapu Bulu,,
|
|
||||||
|
@@ -1,211 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Snom,,
|
|
||||||
2,Frosmoth,,
|
|
||||||
3,Wooloo,,
|
|
||||||
4,Dubwool,,
|
|
||||||
5,Skwovet,,
|
|
||||||
6,Greedent,,
|
|
||||||
7,Swinub,,
|
|
||||||
8,Piloswine,,
|
|
||||||
9,Mamoswine,,
|
|
||||||
10,Mime Jr.,,
|
|
||||||
11,Mr. Mime,,
|
|
||||||
12,Mr. Rime,,
|
|
||||||
13,Smoochum,,
|
|
||||||
14,Jynx,,
|
|
||||||
15,Elekid,,
|
|
||||||
16,Electabuzz,,
|
|
||||||
17,Electivire,,
|
|
||||||
18,Magby,,
|
|
||||||
19,Magmar,,
|
|
||||||
20,Magmortar,,
|
|
||||||
21,Audino,,
|
|
||||||
22,Vanillite,,
|
|
||||||
23,Vanillish,,
|
|
||||||
24,Vanilluxe,,
|
|
||||||
25,Snorunt,,
|
|
||||||
26,Glalie,,
|
|
||||||
27,Froslass,,
|
|
||||||
28,Sneasel,,
|
|
||||||
29,Weavile,,
|
|
||||||
30,Cryogonal,,
|
|
||||||
31,Snover,,
|
|
||||||
32,Abomasnow,,
|
|
||||||
33,Phantump,,
|
|
||||||
34,Trevenant,,
|
|
||||||
35,Swablu,,
|
|
||||||
36,Altaria,,
|
|
||||||
37,Impidimp,,
|
|
||||||
38,Morgrem,,
|
|
||||||
39,Grimmsnarl,,
|
|
||||||
40,Hatenna,,
|
|
||||||
41,Hattrem,,
|
|
||||||
42,Hatterene,,
|
|
||||||
43,Cleffa,,
|
|
||||||
44,Clefairy,,
|
|
||||||
45,Clefable,,
|
|
||||||
46,Mimikyu,,
|
|
||||||
47,Spiritomb,,
|
|
||||||
48,Litwick,,
|
|
||||||
49,Lampent,,
|
|
||||||
50,Chandelure,,
|
|
||||||
51,Gothita,,
|
|
||||||
52,Gothorita,,
|
|
||||||
53,Gothitelle,,
|
|
||||||
54,Solosis,,
|
|
||||||
55,Duosion,,
|
|
||||||
56,Reuniclus,,
|
|
||||||
57,Timburr,,
|
|
||||||
58,Gurdurr,,
|
|
||||||
59,Conkeldurr,,
|
|
||||||
60,Barboach,,
|
|
||||||
61,Whiscash,,
|
|
||||||
62,Magikarp,,
|
|
||||||
63,Gyarados,,
|
|
||||||
64,Basculin,,
|
|
||||||
65,Nidoran♀,,
|
|
||||||
66,Nidorina,,
|
|
||||||
67,Nidoqueen,,
|
|
||||||
68,Nidoran♂,,
|
|
||||||
69,Nidorino,,
|
|
||||||
70,Nidoking,,
|
|
||||||
71,Zigzagoon,,
|
|
||||||
72,Linoone,,
|
|
||||||
73,Obstagoon,,
|
|
||||||
74,Eevee,,
|
|
||||||
75,Vaporeon,,
|
|
||||||
76,Jolteon,,
|
|
||||||
77,Flareon,,
|
|
||||||
78,Umbreon,,
|
|
||||||
79,Espeon,,
|
|
||||||
80,Glaceon,,
|
|
||||||
81,Leafeon,,
|
|
||||||
82,Sylveon,,
|
|
||||||
83,Tyrunt,,
|
|
||||||
84,Tyrantrum,,
|
|
||||||
85,Amaura,,
|
|
||||||
86,Aurorus,,
|
|
||||||
87,Bronzor,,
|
|
||||||
88,Bronzong,,
|
|
||||||
89,Stonjourner,,
|
|
||||||
90,Eiscue,,
|
|
||||||
91,Dewpider,,
|
|
||||||
92,Araquanid,,
|
|
||||||
93,Joltik,,
|
|
||||||
94,Galvantula,,
|
|
||||||
95,Karrablast,,
|
|
||||||
96,Escavalier,,
|
|
||||||
97,Shelmet,,
|
|
||||||
98,Accelgor,,
|
|
||||||
99,Sizzlipede,,
|
|
||||||
100,Centiskorch,,
|
|
||||||
101,Durant,,
|
|
||||||
102,Heatmor,,
|
|
||||||
103,Darumaka,,
|
|
||||||
104,Darmanitan,,
|
|
||||||
105,Ponyta,,
|
|
||||||
106,Rapidash,,
|
|
||||||
107,Absol,,
|
|
||||||
108,Cufant,,
|
|
||||||
109,Copperajah,,
|
|
||||||
110,Dreepy,,
|
|
||||||
111,Drakloak,,
|
|
||||||
112,Dragapult,,
|
|
||||||
113,Bagon,,
|
|
||||||
114,Shelgon,,
|
|
||||||
115,Salamence,,
|
|
||||||
116,Gible,,
|
|
||||||
117,Gabite,,
|
|
||||||
118,Garchomp,,
|
|
||||||
119,Druddigon,,
|
|
||||||
120,Delibird,,
|
|
||||||
121,Cubchoo,,
|
|
||||||
122,Beartic,,
|
|
||||||
123,Omanyte,,
|
|
||||||
124,Omastar,,
|
|
||||||
125,Kabuto,,
|
|
||||||
126,Kabutops,,
|
|
||||||
127,Aerodactyl,,
|
|
||||||
128,Carbink,,
|
|
||||||
129,Beldum,,
|
|
||||||
130,Metang,,
|
|
||||||
131,Metagross,,
|
|
||||||
132,Sinistea,,
|
|
||||||
133,Polteageist,,
|
|
||||||
134,Riolu,,
|
|
||||||
135,Lucario,,
|
|
||||||
136,Deino,,
|
|
||||||
137,Zweilous,,
|
|
||||||
138,Hydreigon,,
|
|
||||||
139,Larvitar,,
|
|
||||||
140,Pupitar,,
|
|
||||||
141,Tyranitar,,
|
|
||||||
142,Bergmite,,
|
|
||||||
143,Avalugg,,
|
|
||||||
144,Zubat,,
|
|
||||||
145,Golbat,,
|
|
||||||
146,Crobat,,
|
|
||||||
147,Tirtouga,,
|
|
||||||
148,Carracosta,,
|
|
||||||
149,Archen,,
|
|
||||||
150,Archeops,,
|
|
||||||
151,Baltoy,,
|
|
||||||
152,Claydol,,
|
|
||||||
153,Golett,,
|
|
||||||
154,Golurk,,
|
|
||||||
155,Yamper,,
|
|
||||||
156,Boltund,,
|
|
||||||
157,Morpeko,,
|
|
||||||
158,Pincurchin,,
|
|
||||||
159,Spheal,,
|
|
||||||
160,Sealeo,,
|
|
||||||
161,Walrein,,
|
|
||||||
162,Dhelmise,,
|
|
||||||
163,Rookidee,,
|
|
||||||
164,Corvisquire,,
|
|
||||||
165,Corviknight,,
|
|
||||||
166,Gossifleur,,
|
|
||||||
167,Eldegoss,,
|
|
||||||
168,Cottonee,,
|
|
||||||
169,Whimsicott,,
|
|
||||||
170,Shuckle,,
|
|
||||||
171,Indeedee,,
|
|
||||||
172,Munchlax,,
|
|
||||||
173,Snorlax,,
|
|
||||||
174,Sableye,,
|
|
||||||
175,Mawile,,
|
|
||||||
176,Rolycoly,,
|
|
||||||
177,Carkol,,
|
|
||||||
178,Coalossal,,
|
|
||||||
179,Ferroseed,,
|
|
||||||
180,Ferrothorn,,
|
|
||||||
181,Noibat,,
|
|
||||||
182,Noivern,,
|
|
||||||
183,Lileep,,
|
|
||||||
184,Cradily,,
|
|
||||||
185,Anorith,,
|
|
||||||
186,Armaldo,,
|
|
||||||
187,Relicanth,,
|
|
||||||
188,Feebas,,
|
|
||||||
189,Milotic,,
|
|
||||||
190,Lapras,,
|
|
||||||
191,Aron,,
|
|
||||||
192,Lairon,,
|
|
||||||
193,Aggron,,
|
|
||||||
194,Dratini,,
|
|
||||||
195,Dragonair,,
|
|
||||||
196,Dragonite,,
|
|
||||||
197,Regirock,,
|
|
||||||
198,Regice,,
|
|
||||||
199,Registeel,,
|
|
||||||
200,Regieleki,,
|
|
||||||
201,Regidrago,,
|
|
||||||
202,Articuno,,
|
|
||||||
203,Zapdos,,
|
|
||||||
204,Moltres,,
|
|
||||||
205,Cobalion,,
|
|
||||||
206,Terrakion,,
|
|
||||||
207,Virizion,,
|
|
||||||
208,Glastrier,,
|
|
||||||
209,Spectrier,,
|
|
||||||
210,Calyrex,,
|
|
||||||
|
@@ -1,212 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Slowpoke,,
|
|
||||||
2,Slowbro,,
|
|
||||||
3,Slowking,,
|
|
||||||
4,Buneary,,
|
|
||||||
5,Lopunny,,
|
|
||||||
6,Happiny,,
|
|
||||||
7,Chansey,,
|
|
||||||
8,Blissey,,
|
|
||||||
9,Skwovet,,
|
|
||||||
10,Greedent,,
|
|
||||||
11,Igglybuff,,
|
|
||||||
12,Jigglypuff,,
|
|
||||||
13,Wigglytuff,,
|
|
||||||
14,Blipbug,,
|
|
||||||
15,Dottler,,
|
|
||||||
16,Orbeetle,,
|
|
||||||
17,Fomantis,,
|
|
||||||
18,Lurantis,,
|
|
||||||
19,Applin,,
|
|
||||||
20,Flapple,,
|
|
||||||
21,Appletun,,
|
|
||||||
22,Fletchling,,
|
|
||||||
23,Fletchinder,,
|
|
||||||
24,Talonflame,,
|
|
||||||
25,Shinx,,
|
|
||||||
26,Luxio,,
|
|
||||||
27,Luxray,,
|
|
||||||
28,Klefki,,
|
|
||||||
29,Pawniard,,
|
|
||||||
30,Bisharp,,
|
|
||||||
31,Abra,,
|
|
||||||
32,Kadabra,,
|
|
||||||
33,Alakazam,,
|
|
||||||
34,Ralts,,
|
|
||||||
35,Kirlia,,
|
|
||||||
36,Gardevoir,,
|
|
||||||
37,Gallade,,
|
|
||||||
38,Krabby,,
|
|
||||||
39,Kingler,,
|
|
||||||
40,Tentacool,,
|
|
||||||
41,Tentacruel,,
|
|
||||||
42,Magikarp,,
|
|
||||||
43,Gyarados,,
|
|
||||||
44,Remoraid,,
|
|
||||||
45,Octillery,,
|
|
||||||
46,Mantyke,,
|
|
||||||
47,Mantine,,
|
|
||||||
48,Wingull,,
|
|
||||||
49,Pelipper,,
|
|
||||||
50,Skorupi,,
|
|
||||||
51,Drapion,,
|
|
||||||
52,Dunsparce,,
|
|
||||||
53,Bouffalant,,
|
|
||||||
54,Lickitung,,
|
|
||||||
55,Lickilicky,,
|
|
||||||
56,Chewtle,,
|
|
||||||
57,Drednaw,,
|
|
||||||
58,Wooper,,
|
|
||||||
59,Quagsire,,
|
|
||||||
60,Goomy,,
|
|
||||||
61,Sliggoo,,
|
|
||||||
62,Goodra,,
|
|
||||||
63,Druddigon,,
|
|
||||||
64,Shelmet,,
|
|
||||||
65,Accelgor,,
|
|
||||||
66,Karrablast,,
|
|
||||||
67,Escavalier,,
|
|
||||||
68,Bulbasaur,,
|
|
||||||
69,Ivysaur,,
|
|
||||||
70,Venusaur,,
|
|
||||||
71,Squirtle,,
|
|
||||||
72,Wartortle,,
|
|
||||||
73,Blastoise,,
|
|
||||||
74,Venipede,,
|
|
||||||
75,Whirlipede,,
|
|
||||||
76,Scolipede,,
|
|
||||||
77,Foongus,,
|
|
||||||
78,Amoonguss,,
|
|
||||||
79,Comfey,,
|
|
||||||
80,Tangela,,
|
|
||||||
81,Tangrowth,,
|
|
||||||
82,Croagunk,,
|
|
||||||
83,Toxicroak,,
|
|
||||||
84,Pichu,,
|
|
||||||
85,Pikachu,,
|
|
||||||
86,Raichu,,
|
|
||||||
87,Zorua,,
|
|
||||||
88,Zoroark,,
|
|
||||||
89,Oranguru,,
|
|
||||||
90,Passimian,,
|
|
||||||
91,Corphish,,
|
|
||||||
92,Crawdaunt,,
|
|
||||||
93,Cramorant,,
|
|
||||||
94,Goldeen,,
|
|
||||||
95,Seaking,,
|
|
||||||
96,Arrokuda,,
|
|
||||||
97,Barraskewda,,
|
|
||||||
98,Staryu,,
|
|
||||||
99,Starmie,,
|
|
||||||
100,Kubfu,,
|
|
||||||
101,Urshifu,,
|
|
||||||
102,Emolga,,
|
|
||||||
103,Dedenne,,
|
|
||||||
104,Morpeko,,
|
|
||||||
105,Magnemite,,
|
|
||||||
106,Magneton,,
|
|
||||||
107,Magnezone,,
|
|
||||||
108,Inkay,,
|
|
||||||
109,Malamar,,
|
|
||||||
110,Wishiwashi,,
|
|
||||||
111,Carvanha,,
|
|
||||||
112,Sharpedo,,
|
|
||||||
113,Lillipup,,
|
|
||||||
114,Herdier,,
|
|
||||||
115,Stoutland,,
|
|
||||||
116,Tauros,,
|
|
||||||
117,Miltank,,
|
|
||||||
118,Scyther,,
|
|
||||||
119,Scizor,,
|
|
||||||
120,Pinsir,,
|
|
||||||
121,Heracross,,
|
|
||||||
122,Dwebble,,
|
|
||||||
123,Crustle,,
|
|
||||||
124,Wimpod,,
|
|
||||||
125,Golisopod,,
|
|
||||||
126,Pincurchin,,
|
|
||||||
127,Mareanie,,
|
|
||||||
128,Toxapex,,
|
|
||||||
129,Clobbopus,,
|
|
||||||
130,Grapploct,,
|
|
||||||
131,Shellder,,
|
|
||||||
132,Cloyster,,
|
|
||||||
133,Sandygast,,
|
|
||||||
134,Palossand,,
|
|
||||||
135,Drifloon,,
|
|
||||||
136,Drifblim,,
|
|
||||||
137,Barboach,,
|
|
||||||
138,Whiscash,,
|
|
||||||
139,Azurill,,
|
|
||||||
140,Marill,,
|
|
||||||
141,Azumarill,,
|
|
||||||
142,Poliwag,,
|
|
||||||
143,Poliwhirl,,
|
|
||||||
144,Poliwrath,,
|
|
||||||
145,Politoed,,
|
|
||||||
146,Psyduck,,
|
|
||||||
147,Golduck,,
|
|
||||||
148,Whismur,,
|
|
||||||
149,Loudred,,
|
|
||||||
150,Exploud,,
|
|
||||||
151,Woobat,,
|
|
||||||
152,Swoobat,,
|
|
||||||
153,Skarmory,,
|
|
||||||
154,Roggenrola,,
|
|
||||||
155,Boldore,,
|
|
||||||
156,Gigalith,,
|
|
||||||
157,Rockruff,,
|
|
||||||
158,Lycanroc,,
|
|
||||||
159,Salandit,,
|
|
||||||
160,Salazzle,,
|
|
||||||
161,Scraggy,,
|
|
||||||
162,Scrafty,,
|
|
||||||
163,Mienfoo,,
|
|
||||||
164,Mienshao,,
|
|
||||||
165,Jangmo-o,,
|
|
||||||
166,Hakamo-o,,
|
|
||||||
167,Kommo-o,,
|
|
||||||
168,Sandshrew,,
|
|
||||||
169,Sandslash,,
|
|
||||||
170,Cubone,,
|
|
||||||
171,Marowak,,
|
|
||||||
172,Kangaskhan,,
|
|
||||||
173,Torkoal,,
|
|
||||||
174,Silicobra,,
|
|
||||||
175,Sandaconda,,
|
|
||||||
176,Sandile,,
|
|
||||||
177,Krokorok,,
|
|
||||||
178,Krookodile,,
|
|
||||||
179,Rufflet,,
|
|
||||||
180,Braviary,,
|
|
||||||
181,Vullaby,,
|
|
||||||
182,Mandibuzz,,
|
|
||||||
183,Rhyhorn,,
|
|
||||||
184,Rhydon,,
|
|
||||||
185,Rhyperior,,
|
|
||||||
186,Larvesta,,
|
|
||||||
187,Volcarona,,
|
|
||||||
188,Chinchou,,
|
|
||||||
189,Lanturn,,
|
|
||||||
190,Wailmer,,
|
|
||||||
191,Wailord,,
|
|
||||||
192,Frillish,,
|
|
||||||
193,Jellicent,,
|
|
||||||
194,Skrelp,,
|
|
||||||
195,Dragalge,,
|
|
||||||
196,Clauncher,,
|
|
||||||
197,Clawitzer,,
|
|
||||||
198,Horsea,,
|
|
||||||
199,Seadra,,
|
|
||||||
200,Kingdra,,
|
|
||||||
201,Petilil,,
|
|
||||||
202,Lilligant,,
|
|
||||||
203,Combee,,
|
|
||||||
204,Vespiquen,,
|
|
||||||
205,Exeggcute,,
|
|
||||||
206,Exeggutor,,
|
|
||||||
207,Ditto,,
|
|
||||||
208,Porygon,,
|
|
||||||
209,Porygon2,,
|
|
||||||
210,Porygon-Z,,
|
|
||||||
211,Zarude,,
|
|
||||||
|
@@ -1,401 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Grookey,,
|
|
||||||
2,Thwackey,,
|
|
||||||
3,Rillaboom,,
|
|
||||||
4,Scorbunny,,
|
|
||||||
5,Raboot,,
|
|
||||||
6,Cinderace,,
|
|
||||||
7,Sobble,,
|
|
||||||
8,Drizzile,,
|
|
||||||
9,Inteleon,,
|
|
||||||
10,Blipbug,,
|
|
||||||
11,Dottler,,
|
|
||||||
12,Orbeetle,,
|
|
||||||
13,Caterpie,,
|
|
||||||
14,Metapod,,
|
|
||||||
15,Butterfree,,
|
|
||||||
16,Grubbin,,
|
|
||||||
17,Charjabug,,
|
|
||||||
18,Vikavolt,,
|
|
||||||
19,Hoothoot,,
|
|
||||||
20,Noctowl,,
|
|
||||||
21,Rookidee,,
|
|
||||||
22,Corvisquire,,
|
|
||||||
23,Corviknight,,
|
|
||||||
24,Skwovet,,
|
|
||||||
25,Greedent,,
|
|
||||||
26,Pidove,,
|
|
||||||
27,Tranquill,,
|
|
||||||
28,Unfezant,,
|
|
||||||
29,Nickit,,
|
|
||||||
30,Thievul,,
|
|
||||||
31,Zigzagoon,,
|
|
||||||
32,Linoone,,
|
|
||||||
33,Obstagoon,,
|
|
||||||
34,Wooloo,,
|
|
||||||
35,Dubwool,,
|
|
||||||
36,Lotad,,
|
|
||||||
37,Lombre,,
|
|
||||||
38,Ludicolo,,
|
|
||||||
39,Seedot,,
|
|
||||||
40,Nuzleaf,,
|
|
||||||
41,Shiftry,,
|
|
||||||
42,Chewtle,,
|
|
||||||
43,Drednaw,,
|
|
||||||
44,Purrloin,,
|
|
||||||
45,Liepard,,
|
|
||||||
46,Yamper,,
|
|
||||||
47,Boltund,,
|
|
||||||
48,Bunnelby,,
|
|
||||||
49,Diggersby,,
|
|
||||||
50,Minccino,,
|
|
||||||
51,Cinccino,,
|
|
||||||
52,Bounsweet,,
|
|
||||||
53,Steenee,,
|
|
||||||
54,Tsareena,,
|
|
||||||
55,Oddish,,
|
|
||||||
56,Gloom,,
|
|
||||||
57,Vileplume,,
|
|
||||||
58,Bellossom,,
|
|
||||||
59,Budew,,
|
|
||||||
60,Roselia,,
|
|
||||||
61,Roserade,,
|
|
||||||
62,Wingull,,
|
|
||||||
63,Pelipper,,
|
|
||||||
64,Joltik,,
|
|
||||||
65,Galvantula,,
|
|
||||||
66,Electrike,,
|
|
||||||
67,Manectric,,
|
|
||||||
68,Vulpix,,
|
|
||||||
69,Ninetales,,
|
|
||||||
70,Growlithe,,
|
|
||||||
71,Arcanine,,
|
|
||||||
72,Vanillite,,
|
|
||||||
73,Vanillish,,
|
|
||||||
74,Vanilluxe,,
|
|
||||||
75,Swinub,,
|
|
||||||
76,Piloswine,,
|
|
||||||
77,Mamoswine,,
|
|
||||||
78,Delibird,,
|
|
||||||
79,Snorunt,,
|
|
||||||
80,Glalie,,
|
|
||||||
81,Froslass,,
|
|
||||||
82,Baltoy,,
|
|
||||||
83,Claydol,,
|
|
||||||
84,Mudbray,,
|
|
||||||
85,Mudsdale,,
|
|
||||||
86,Dwebble,,
|
|
||||||
87,Crustle,,
|
|
||||||
88,Golett,,
|
|
||||||
89,Golurk,,
|
|
||||||
90,Munna,,
|
|
||||||
91,Musharna,,
|
|
||||||
92,Natu,,
|
|
||||||
93,Xatu,,
|
|
||||||
94,Stufful,,
|
|
||||||
95,Bewear,,
|
|
||||||
96,Snover,,
|
|
||||||
97,Abomasnow,,
|
|
||||||
98,Krabby,,
|
|
||||||
99,Kingler,,
|
|
||||||
100,Wooper,,
|
|
||||||
101,Quagsire,,
|
|
||||||
102,Corphish,,
|
|
||||||
103,Crawdaunt,,
|
|
||||||
104,Nincada,,
|
|
||||||
105,Ninjask,,
|
|
||||||
106,Shedinja,,
|
|
||||||
107,Tyrogue,,
|
|
||||||
108,Hitmonlee,,
|
|
||||||
109,Hitmonchan,,
|
|
||||||
110,Hitmontop,,
|
|
||||||
111,Pancham,,
|
|
||||||
112,Pangoro,,
|
|
||||||
113,Klink,,
|
|
||||||
114,Klang,,
|
|
||||||
115,Klinklang,,
|
|
||||||
116,Combee,,
|
|
||||||
117,Vespiquen,,
|
|
||||||
118,Bronzor,,
|
|
||||||
119,Bronzong,,
|
|
||||||
120,Ralts,,
|
|
||||||
121,Kirlia,,
|
|
||||||
122,Gardevoir,,
|
|
||||||
123,Gallade,,
|
|
||||||
124,Drifloon,,
|
|
||||||
125,Drifblim,,
|
|
||||||
126,Gossifleur,,
|
|
||||||
127,Eldegoss,,
|
|
||||||
128,Cherubi,,
|
|
||||||
129,Cherrim,,
|
|
||||||
130,Stunky,,
|
|
||||||
131,Skuntank,,
|
|
||||||
132,Tympole,,
|
|
||||||
133,Palpitoad,,
|
|
||||||
134,Seismitoad,,
|
|
||||||
135,Duskull,,
|
|
||||||
136,Dusclops,,
|
|
||||||
137,Dusknoir,,
|
|
||||||
138,Machop,,
|
|
||||||
139,Machoke,,
|
|
||||||
140,Machamp,,
|
|
||||||
141,Gastly,,
|
|
||||||
142,Haunter,,
|
|
||||||
143,Gengar,,
|
|
||||||
144,Magikarp,,
|
|
||||||
145,Gyarados,,
|
|
||||||
146,Goldeen,,
|
|
||||||
147,Seaking,,
|
|
||||||
148,Remoraid,,
|
|
||||||
149,Octillery,,
|
|
||||||
150,Shellder,,
|
|
||||||
151,Cloyster,,
|
|
||||||
152,Feebas,,
|
|
||||||
153,Milotic,,
|
|
||||||
154,Basculin,,
|
|
||||||
155,Wishiwashi,,
|
|
||||||
156,Pyukumuku,,
|
|
||||||
157,Trubbish,,
|
|
||||||
158,Garbodor,,
|
|
||||||
159,Sizzlipede,,
|
|
||||||
160,Centiskorch,,
|
|
||||||
161,Rolycoly,,
|
|
||||||
162,Carkol,,
|
|
||||||
163,Coalossal,,
|
|
||||||
164,Diglett,,
|
|
||||||
165,Dugtrio,,
|
|
||||||
166,Drilbur,,
|
|
||||||
167,Excadrill,,
|
|
||||||
168,Roggenrola,,
|
|
||||||
169,Boldore,,
|
|
||||||
170,Gigalith,,
|
|
||||||
171,Timburr,,
|
|
||||||
172,Gurdurr,,
|
|
||||||
173,Conkeldurr,,
|
|
||||||
174,Woobat,,
|
|
||||||
175,Swoobat,,
|
|
||||||
176,Noibat,,
|
|
||||||
177,Noivern,,
|
|
||||||
178,Onix,,
|
|
||||||
179,Steelix,,
|
|
||||||
180,Arrokuda,,
|
|
||||||
181,Barraskewda,,
|
|
||||||
182,Meowth,,
|
|
||||||
183,Perrserker,,
|
|
||||||
184,Persian,,
|
|
||||||
185,Milcery,,
|
|
||||||
186,Alcremie,,
|
|
||||||
187,Cutiefly,,
|
|
||||||
188,Ribombee,,
|
|
||||||
189,Ferroseed,,
|
|
||||||
190,Ferrothorn,,
|
|
||||||
191,Pumpkaboo,,
|
|
||||||
192,Gourgeist,,
|
|
||||||
193,Pichu,,
|
|
||||||
194,Pikachu,,
|
|
||||||
195,Raichu,,
|
|
||||||
196,Eevee,,
|
|
||||||
197,Vaporeon,,
|
|
||||||
198,Jolteon,,
|
|
||||||
199,Flareon,,
|
|
||||||
200,Espeon,,
|
|
||||||
201,Umbreon,,
|
|
||||||
202,Leafeon,,
|
|
||||||
203,Glaceon,,
|
|
||||||
204,Sylveon,,
|
|
||||||
205,Applin,,
|
|
||||||
206,Flapple,,
|
|
||||||
207,Appletun,,
|
|
||||||
208,Espurr,,
|
|
||||||
209,Meowstic,,
|
|
||||||
210,Swirlix,,
|
|
||||||
211,Slurpuff,,
|
|
||||||
212,Spritzee,,
|
|
||||||
213,Aromatisse,,
|
|
||||||
214,Dewpider,,
|
|
||||||
215,Araquanid,,
|
|
||||||
216,Wynaut,,
|
|
||||||
217,Wobbuffet,,
|
|
||||||
218,Farfetch’d,,
|
|
||||||
219,Sirfetch’d,,
|
|
||||||
220,Chinchou,,
|
|
||||||
221,Lanturn,,
|
|
||||||
222,Croagunk,,
|
|
||||||
223,Toxicroak,,
|
|
||||||
224,Scraggy,,
|
|
||||||
225,Scrafty,,
|
|
||||||
226,Stunfisk,,
|
|
||||||
227,Shuckle,,
|
|
||||||
228,Barboach,,
|
|
||||||
229,Whiscash,,
|
|
||||||
230,Shellos,,
|
|
||||||
231,Gastrodon,,
|
|
||||||
232,Wimpod,,
|
|
||||||
233,Golisopod,,
|
|
||||||
234,Binacle,,
|
|
||||||
235,Barbaracle,,
|
|
||||||
236,Corsola,,
|
|
||||||
237,Cursola,,
|
|
||||||
238,Impidimp,,
|
|
||||||
239,Morgrem,,
|
|
||||||
240,Grimmsnarl,,
|
|
||||||
241,Hatenna,,
|
|
||||||
242,Hattrem,,
|
|
||||||
243,Hatterene,,
|
|
||||||
244,Salandit,,
|
|
||||||
245,Salazzle,,
|
|
||||||
246,Pawniard,,
|
|
||||||
247,Bisharp,,
|
|
||||||
248,Throh,,
|
|
||||||
249,Sawk,,
|
|
||||||
250,Koffing,,
|
|
||||||
251,Weezing,,
|
|
||||||
252,Bonsly,,
|
|
||||||
253,Sudowoodo,,
|
|
||||||
254,Cleffa,,
|
|
||||||
255,Clefairy,,
|
|
||||||
256,Clefable,,
|
|
||||||
257,Togepi,,
|
|
||||||
258,Togetic,,
|
|
||||||
259,Togekiss,,
|
|
||||||
260,Munchlax,,
|
|
||||||
261,Snorlax,,
|
|
||||||
262,Cottonee,,
|
|
||||||
263,Whimsicott,,
|
|
||||||
264,Rhyhorn,,
|
|
||||||
265,Rhydon,,
|
|
||||||
266,Rhyperior,,
|
|
||||||
267,Gothita,,
|
|
||||||
268,Gothorita,,
|
|
||||||
269,Gothitelle,,
|
|
||||||
270,Solosis,,
|
|
||||||
271,Duosion,,
|
|
||||||
272,Reuniclus,,
|
|
||||||
273,Karrablast,,
|
|
||||||
274,Escavalier,,
|
|
||||||
275,Shelmet,,
|
|
||||||
276,Accelgor,,
|
|
||||||
277,Elgyem,,
|
|
||||||
278,Beheeyem,,
|
|
||||||
279,Cubchoo,,
|
|
||||||
280,Beartic,,
|
|
||||||
281,Rufflet,,
|
|
||||||
282,Braviary,,
|
|
||||||
283,Vullaby,,
|
|
||||||
284,Mandibuzz,,
|
|
||||||
285,Skorupi,,
|
|
||||||
286,Drapion,,
|
|
||||||
287,Litwick,,
|
|
||||||
288,Lampent,,
|
|
||||||
289,Chandelure,,
|
|
||||||
290,Inkay,,
|
|
||||||
291,Malamar,,
|
|
||||||
292,Sneasel,,
|
|
||||||
293,Weavile,,
|
|
||||||
294,Sableye,,
|
|
||||||
295,Mawile,,
|
|
||||||
296,Maractus,,
|
|
||||||
297,Sigilyph,,
|
|
||||||
298,Riolu,,
|
|
||||||
299,Lucario,,
|
|
||||||
300,Torkoal,,
|
|
||||||
301,Mimikyu,,
|
|
||||||
302,Cufant,,
|
|
||||||
303,Copperajah,,
|
|
||||||
304,Qwilfish,,
|
|
||||||
305,Frillish,,
|
|
||||||
306,Jellicent,,
|
|
||||||
307,Mareanie,,
|
|
||||||
308,Toxapex,,
|
|
||||||
309,Cramorant,,
|
|
||||||
310,Toxel,,
|
|
||||||
311,Toxtricity,,
|
|
||||||
312,Silicobra,,
|
|
||||||
313,Sandaconda,,
|
|
||||||
314,Hippopotas,,
|
|
||||||
315,Hippowdon,,
|
|
||||||
316,Durant,,
|
|
||||||
317,Heatmor,,
|
|
||||||
318,Helioptile,,
|
|
||||||
319,Heliolisk,,
|
|
||||||
320,Hawlucha,,
|
|
||||||
321,Trapinch,,
|
|
||||||
322,Vibrava,,
|
|
||||||
323,Flygon,,
|
|
||||||
324,Axew,,
|
|
||||||
325,Fraxure,,
|
|
||||||
326,Haxorus,,
|
|
||||||
327,Yamask,,
|
|
||||||
328,Runerigus,,
|
|
||||||
329,Cofagrigus,,
|
|
||||||
330,Honedge,,
|
|
||||||
331,Doublade,,
|
|
||||||
332,Aegislash,,
|
|
||||||
333,Ponyta,,
|
|
||||||
334,Rapidash,,
|
|
||||||
335,Sinistea,,
|
|
||||||
336,Polteageist,,
|
|
||||||
337,Indeedee,,
|
|
||||||
338,Phantump,,
|
|
||||||
339,Trevenant,,
|
|
||||||
340,Morelull,,
|
|
||||||
341,Shiinotic,,
|
|
||||||
342,Oranguru,,
|
|
||||||
343,Passimian,,
|
|
||||||
344,Morpeko,,
|
|
||||||
345,Falinks,,
|
|
||||||
346,Drampa,,
|
|
||||||
347,Turtonator,,
|
|
||||||
348,Togedemaru,,
|
|
||||||
349,Snom,,
|
|
||||||
350,Frosmoth,,
|
|
||||||
351,Clobbopus,,
|
|
||||||
352,Grapploct,,
|
|
||||||
353,Pincurchin,,
|
|
||||||
354,Mantyke,,
|
|
||||||
355,Mantine,,
|
|
||||||
356,Wailmer,,
|
|
||||||
357,Wailord,,
|
|
||||||
358,Bergmite,,
|
|
||||||
359,Avalugg,,
|
|
||||||
360,Dhelmise,,
|
|
||||||
361,Lapras,,
|
|
||||||
362,Lunatone,,
|
|
||||||
363,Solrock,,
|
|
||||||
364,Mime Jr.,,
|
|
||||||
365,Mr. Mime,,
|
|
||||||
366,Mr. Rime,,
|
|
||||||
367,Darumaka,,
|
|
||||||
368,Darmanitan,,
|
|
||||||
369,Stonjourner,,
|
|
||||||
370,Eiscue,,
|
|
||||||
371,Duraludon,,
|
|
||||||
372,Rotom,,
|
|
||||||
373,Ditto,,
|
|
||||||
374,Dracozolt,,
|
|
||||||
375,Arctozolt,,
|
|
||||||
376,Dracovish,,
|
|
||||||
377,Arctovish,,
|
|
||||||
378,Charmander,,
|
|
||||||
379,Charmeleon,,
|
|
||||||
380,Charizard,,
|
|
||||||
381,Type: Null,,
|
|
||||||
382,Silvally,,
|
|
||||||
383,Larvitar,,
|
|
||||||
384,Pupitar,,
|
|
||||||
385,Tyranitar,,
|
|
||||||
386,Deino,,
|
|
||||||
387,Zweilous,,
|
|
||||||
388,Hydreigon,,
|
|
||||||
389,Goomy,,
|
|
||||||
390,Sliggoo,,
|
|
||||||
391,Goodra,,
|
|
||||||
392,Jangmo-o,,
|
|
||||||
393,Hakamo-o,,
|
|
||||||
394,Kommo-o,,
|
|
||||||
395,Dreepy,,
|
|
||||||
396,Drakloak,,
|
|
||||||
397,Dragapult,,
|
|
||||||
398,Zacian,,
|
|
||||||
399,Zamazenta,,
|
|
||||||
400,Eternatus,,
|
|
||||||
|
@@ -1,161 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Pikipek,,
|
|
||||||
2,Trumbeak,,
|
|
||||||
3,Toucannon,,
|
|
||||||
4,Yungoos,,
|
|
||||||
5,Gumshoos,,
|
|
||||||
6,Rattata,,
|
|
||||||
7,Raticate,,
|
|
||||||
8,Caterpie,,
|
|
||||||
9,Metapod,,
|
|
||||||
10,Butterfree,,
|
|
||||||
11,Grubbin,,
|
|
||||||
12,Charjabug,,
|
|
||||||
13,Vikavolt,,
|
|
||||||
14,Bonsly,,
|
|
||||||
15,Sudowoodo,,
|
|
||||||
16,Happiny,,
|
|
||||||
17,Chansey,,
|
|
||||||
18,Blissey,,
|
|
||||||
19,Wingull,,
|
|
||||||
20,Pelipper,,
|
|
||||||
21,Crabrawler,,
|
|
||||||
22,Crabominable,,
|
|
||||||
23,Gastly,,
|
|
||||||
24,Haunter,,
|
|
||||||
25,Gengar,,
|
|
||||||
26,Zubat,,
|
|
||||||
27,Golbat,,
|
|
||||||
28,Crobat,,
|
|
||||||
29,Diglett,,
|
|
||||||
30,Dugtrio,,
|
|
||||||
31,Oricorio,,
|
|
||||||
32,Psyduck,,
|
|
||||||
33,Golduck,,
|
|
||||||
34,Magikarp,,
|
|
||||||
35,Gyarados,,
|
|
||||||
36,Barboach,,
|
|
||||||
37,Whiscash,,
|
|
||||||
38,Tentacool,,
|
|
||||||
39,Tentacruel,,
|
|
||||||
40,Finneon,,
|
|
||||||
41,Lumineon,,
|
|
||||||
42,Wishiwashi,,
|
|
||||||
43,Luvdisc,,
|
|
||||||
44,Corsola,,
|
|
||||||
45,Mareanie,,
|
|
||||||
46,Toxapex,,
|
|
||||||
47,Remoraid,,
|
|
||||||
48,Octillery,,
|
|
||||||
49,Mantyke,,
|
|
||||||
50,Mantine,,
|
|
||||||
51,Lillipup,,
|
|
||||||
52,Herdier,,
|
|
||||||
53,Stoutland,,
|
|
||||||
54,Eevee,,
|
|
||||||
55,Vaporeon,,
|
|
||||||
56,Jolteon,,
|
|
||||||
57,Flareon,,
|
|
||||||
58,Espeon,,
|
|
||||||
59,Umbreon,,
|
|
||||||
60,Leafeon,,
|
|
||||||
61,Glaceon,,
|
|
||||||
62,Sylveon,,
|
|
||||||
63,Mareep,,
|
|
||||||
64,Flaaffy,,
|
|
||||||
65,Ampharos,,
|
|
||||||
66,Mudbray,,
|
|
||||||
67,Mudsdale,,
|
|
||||||
68,Igglybuff,,
|
|
||||||
69,Jigglypuff,,
|
|
||||||
70,Wigglytuff,,
|
|
||||||
71,Tauros,,
|
|
||||||
72,Miltank,,
|
|
||||||
73,Surskit,,
|
|
||||||
74,Masquerain,,
|
|
||||||
75,Dewpider,,
|
|
||||||
76,Araquanid,,
|
|
||||||
77,Fomantis,,
|
|
||||||
78,Lurantis,,
|
|
||||||
79,Morelull,,
|
|
||||||
80,Shiinotic,,
|
|
||||||
81,Paras,,
|
|
||||||
82,Parasect,,
|
|
||||||
83,Poliwag,,
|
|
||||||
84,Poliwhirl,,
|
|
||||||
85,Poliwrath,,
|
|
||||||
86,Politoed,,
|
|
||||||
87,Goldeen,,
|
|
||||||
88,Seaking,,
|
|
||||||
89,Basculin,,
|
|
||||||
90,Feebas,,
|
|
||||||
91,Milotic,,
|
|
||||||
92,Alomomola,,
|
|
||||||
93,Fletchling,,
|
|
||||||
94,Fletchinder,,
|
|
||||||
95,Talonflame,,
|
|
||||||
96,Salandit,,
|
|
||||||
97,Salazzle,,
|
|
||||||
98,Cubone,,
|
|
||||||
99,Marowak,,
|
|
||||||
100,Kangaskhan,,
|
|
||||||
101,Magby,,
|
|
||||||
102,Magmar,,
|
|
||||||
103,Magmortar,,
|
|
||||||
104,Larvesta,,
|
|
||||||
105,Volcarona,,
|
|
||||||
106,Stufful,,
|
|
||||||
107,Bewear,,
|
|
||||||
108,Bounsweet,,
|
|
||||||
109,Steenee,,
|
|
||||||
110,Tsareena,,
|
|
||||||
111,Comfey,,
|
|
||||||
112,Pinsir,,
|
|
||||||
113,Hoothoot,,
|
|
||||||
114,Noctowl,,
|
|
||||||
115,Kecleon,,
|
|
||||||
116,Oranguru,,
|
|
||||||
117,Passimian,,
|
|
||||||
118,Goomy,,
|
|
||||||
119,Sliggoo,,
|
|
||||||
120,Goodra,,
|
|
||||||
121,Castform,,
|
|
||||||
122,Wimpod,,
|
|
||||||
123,Golisopod,,
|
|
||||||
124,Staryu,,
|
|
||||||
125,Starmie,,
|
|
||||||
126,Sandygast,,
|
|
||||||
127,Palossand,,
|
|
||||||
128,Omanyte,,
|
|
||||||
129,Omastar,,
|
|
||||||
130,Kabuto,,
|
|
||||||
131,Kabutops,,
|
|
||||||
132,Lileep,,
|
|
||||||
133,Cradily,,
|
|
||||||
134,Anorith,,
|
|
||||||
135,Armaldo,,
|
|
||||||
136,Cranidos,,
|
|
||||||
137,Rampardos,,
|
|
||||||
138,Shieldon,,
|
|
||||||
139,Bastiodon,,
|
|
||||||
140,Archen,,
|
|
||||||
141,Archeops,,
|
|
||||||
142,Tirtouga,,
|
|
||||||
143,Carracosta,,
|
|
||||||
144,Tyrunt,,
|
|
||||||
145,Tyrantrum,,
|
|
||||||
146,Amaura,,
|
|
||||||
147,Aurorus,,
|
|
||||||
148,Larvitar,,
|
|
||||||
149,Pupitar,,
|
|
||||||
150,Tyranitar,,
|
|
||||||
151,Phantump,,
|
|
||||||
152,Trevenant,,
|
|
||||||
153,Natu,,
|
|
||||||
154,Xatu,,
|
|
||||||
155,Nosepass,,
|
|
||||||
156,Probopass,,
|
|
||||||
157,Pyukumuku,,
|
|
||||||
158,Chinchou,,
|
|
||||||
159,Lanturn,,
|
|
||||||
160,Tapu Lele,,
|
|
||||||
|
@@ -1,404 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Rowlet,,
|
|
||||||
2,Dartrix,,
|
|
||||||
3,Decidueye,,
|
|
||||||
4,Litten,,
|
|
||||||
5,Torracat,,
|
|
||||||
6,Incineroar,,
|
|
||||||
7,Popplio,,
|
|
||||||
8,Brionne,,
|
|
||||||
9,Primarina,,
|
|
||||||
10,Pikipek,,
|
|
||||||
11,Trumbeak,,
|
|
||||||
12,Toucannon,,
|
|
||||||
13,Yungoos,,
|
|
||||||
14,Gumshoos,,
|
|
||||||
15,Rattata,,
|
|
||||||
16,Raticate,,
|
|
||||||
17,Caterpie,,
|
|
||||||
18,Metapod,,
|
|
||||||
19,Butterfree,,
|
|
||||||
20,Ledyba,,
|
|
||||||
21,Ledian,,
|
|
||||||
22,Spinarak,,
|
|
||||||
23,Ariados,,
|
|
||||||
24,Buneary,,
|
|
||||||
25,Lopunny,,
|
|
||||||
26,Inkay,,
|
|
||||||
27,Malamar,,
|
|
||||||
28,Zorua,,
|
|
||||||
29,Zoroark,,
|
|
||||||
30,Furfrou,,
|
|
||||||
31,Pichu,,
|
|
||||||
32,Pikachu,,
|
|
||||||
33,Raichu,,
|
|
||||||
34,Grubbin,,
|
|
||||||
35,Charjabug,,
|
|
||||||
36,Vikavolt,,
|
|
||||||
37,Bonsly,,
|
|
||||||
38,Sudowoodo,,
|
|
||||||
39,Happiny,,
|
|
||||||
40,Chansey,,
|
|
||||||
41,Blissey,,
|
|
||||||
42,Munchlax,,
|
|
||||||
43,Snorlax,,
|
|
||||||
44,Slowpoke,,
|
|
||||||
45,Slowbro,,
|
|
||||||
46,Slowking,,
|
|
||||||
47,Wingull,,
|
|
||||||
48,Pelipper,,
|
|
||||||
49,Abra,,
|
|
||||||
50,Kadabra,,
|
|
||||||
51,Alakazam,,
|
|
||||||
52,Meowth,,
|
|
||||||
53,Persian,,
|
|
||||||
54,Magnemite,,
|
|
||||||
55,Magneton,,
|
|
||||||
56,Magnezone,,
|
|
||||||
57,Grimer,,
|
|
||||||
58,Muk,,
|
|
||||||
59,Mime Jr.,,
|
|
||||||
60,Mr. Mime,,
|
|
||||||
61,Ekans,,
|
|
||||||
62,Arbok,,
|
|
||||||
63,Dunsparce,,
|
|
||||||
64,Growlithe,,
|
|
||||||
65,Arcanine,,
|
|
||||||
66,Drowzee,,
|
|
||||||
67,Hypno,,
|
|
||||||
68,Makuhita,,
|
|
||||||
69,Hariyama,,
|
|
||||||
70,Smeargle,,
|
|
||||||
71,Crabrawler,,
|
|
||||||
72,Crabominable,,
|
|
||||||
73,Gastly,,
|
|
||||||
74,Haunter,,
|
|
||||||
75,Gengar,,
|
|
||||||
76,Drifloon,,
|
|
||||||
77,Drifblim,,
|
|
||||||
78,Murkrow,,
|
|
||||||
79,Honchkrow,,
|
|
||||||
80,Zubat,,
|
|
||||||
81,Golbat,,
|
|
||||||
82,Crobat,,
|
|
||||||
83,Noibat,,
|
|
||||||
84,Noivern,,
|
|
||||||
85,Diglett,,
|
|
||||||
86,Dugtrio,,
|
|
||||||
87,Spearow,,
|
|
||||||
88,Fearow,,
|
|
||||||
89,Rufflet,,
|
|
||||||
90,Braviary,,
|
|
||||||
91,Vullaby,,
|
|
||||||
92,Mandibuzz,,
|
|
||||||
93,Mankey,,
|
|
||||||
94,Primeape,,
|
|
||||||
95,Delibird,,
|
|
||||||
96,Hawlucha,,
|
|
||||||
97,Oricorio,,
|
|
||||||
98,Cutiefly,,
|
|
||||||
99,Ribombee,,
|
|
||||||
100,Flabébé,,
|
|
||||||
101,Floette,,
|
|
||||||
102,Florges,,
|
|
||||||
103,Petilil,,
|
|
||||||
104,Lilligant,,
|
|
||||||
105,Cottonee,,
|
|
||||||
106,Whimsicott,,
|
|
||||||
107,Psyduck,,
|
|
||||||
108,Golduck,,
|
|
||||||
109,Smoochum,,
|
|
||||||
110,Jynx,,
|
|
||||||
111,Magikarp,,
|
|
||||||
112,Gyarados,,
|
|
||||||
113,Barboach,,
|
|
||||||
114,Whiscash,,
|
|
||||||
115,Seel,,
|
|
||||||
116,Dewgong,,
|
|
||||||
117,Machop,,
|
|
||||||
118,Machoke,,
|
|
||||||
119,Machamp,,
|
|
||||||
120,Roggenrola,,
|
|
||||||
121,Boldore,,
|
|
||||||
122,Gigalith,,
|
|
||||||
123,Carbink,,
|
|
||||||
124,Sableye,,
|
|
||||||
125,Mawile,,
|
|
||||||
126,Rockruff,,
|
|
||||||
127,Lycanroc,,
|
|
||||||
128,Spinda,,
|
|
||||||
129,Tentacool,,
|
|
||||||
130,Tentacruel,,
|
|
||||||
131,Finneon,,
|
|
||||||
132,Lumineon,,
|
|
||||||
133,Wishiwashi,,
|
|
||||||
134,Luvdisc,,
|
|
||||||
135,Corsola,,
|
|
||||||
136,Mareanie,,
|
|
||||||
137,Toxapex,,
|
|
||||||
138,Shellder,,
|
|
||||||
139,Cloyster,,
|
|
||||||
140,Clamperl,,
|
|
||||||
141,Huntail,,
|
|
||||||
142,Gorebyss,,
|
|
||||||
143,Remoraid,,
|
|
||||||
144,Octillery,,
|
|
||||||
145,Mantyke,,
|
|
||||||
146,Mantine,,
|
|
||||||
147,Bagon,,
|
|
||||||
148,Shelgon,,
|
|
||||||
149,Salamence,,
|
|
||||||
150,Lillipup,,
|
|
||||||
151,Herdier,,
|
|
||||||
152,Stoutland,,
|
|
||||||
153,Eevee,,
|
|
||||||
154,Vaporeon,,
|
|
||||||
155,Jolteon,,
|
|
||||||
156,Flareon,,
|
|
||||||
157,Espeon,,
|
|
||||||
158,Umbreon,,
|
|
||||||
159,Leafeon,,
|
|
||||||
160,Glaceon,,
|
|
||||||
161,Sylveon,,
|
|
||||||
162,Mareep,,
|
|
||||||
163,Flaaffy,,
|
|
||||||
164,Ampharos,,
|
|
||||||
165,Mudbray,,
|
|
||||||
166,Mudsdale,,
|
|
||||||
167,Igglybuff,,
|
|
||||||
168,Jigglypuff,,
|
|
||||||
169,Wigglytuff,,
|
|
||||||
170,Tauros,,
|
|
||||||
171,Miltank,,
|
|
||||||
172,Surskit,,
|
|
||||||
173,Masquerain,,
|
|
||||||
174,Dewpider,,
|
|
||||||
175,Araquanid,,
|
|
||||||
176,Fomantis,,
|
|
||||||
177,Lurantis,,
|
|
||||||
178,Morelull,,
|
|
||||||
179,Shiinotic,,
|
|
||||||
180,Paras,,
|
|
||||||
181,Parasect,,
|
|
||||||
182,Poliwag,,
|
|
||||||
183,Poliwhirl,,
|
|
||||||
184,Poliwrath,,
|
|
||||||
185,Politoed,,
|
|
||||||
186,Goldeen,,
|
|
||||||
187,Seaking,,
|
|
||||||
188,Basculin,,
|
|
||||||
189,Feebas,,
|
|
||||||
190,Milotic,,
|
|
||||||
191,Alomomola,,
|
|
||||||
192,Fletchling,,
|
|
||||||
193,Fletchinder,,
|
|
||||||
194,Talonflame,,
|
|
||||||
195,Salandit,,
|
|
||||||
196,Salazzle,,
|
|
||||||
197,Cubone,,
|
|
||||||
198,Marowak,,
|
|
||||||
199,Kangaskhan,,
|
|
||||||
200,Magby,,
|
|
||||||
201,Magmar,,
|
|
||||||
202,Magmortar,,
|
|
||||||
203,Larvesta,,
|
|
||||||
204,Volcarona,,
|
|
||||||
205,Stufful,,
|
|
||||||
206,Bewear,,
|
|
||||||
207,Bounsweet,,
|
|
||||||
208,Steenee,,
|
|
||||||
209,Tsareena,,
|
|
||||||
210,Comfey,,
|
|
||||||
211,Pinsir,,
|
|
||||||
212,Hoothoot,,
|
|
||||||
213,Noctowl,,
|
|
||||||
214,Kecleon,,
|
|
||||||
215,Oranguru,,
|
|
||||||
216,Passimian,,
|
|
||||||
217,Goomy,,
|
|
||||||
218,Sliggoo,,
|
|
||||||
219,Goodra,,
|
|
||||||
220,Castform,,
|
|
||||||
221,Wimpod,,
|
|
||||||
222,Golisopod,,
|
|
||||||
223,Staryu,,
|
|
||||||
224,Starmie,,
|
|
||||||
225,Sandygast,,
|
|
||||||
226,Palossand,,
|
|
||||||
227,Omanyte,,
|
|
||||||
228,Omastar,,
|
|
||||||
229,Kabuto,,
|
|
||||||
230,Kabutops,,
|
|
||||||
231,Lileep,,
|
|
||||||
232,Cradily,,
|
|
||||||
233,Anorith,,
|
|
||||||
234,Armaldo,,
|
|
||||||
235,Cranidos,,
|
|
||||||
236,Rampardos,,
|
|
||||||
237,Shieldon,,
|
|
||||||
238,Bastiodon,,
|
|
||||||
239,Archen,,
|
|
||||||
240,Archeops,,
|
|
||||||
241,Tirtouga,,
|
|
||||||
242,Carracosta,,
|
|
||||||
243,Tyrunt,,
|
|
||||||
244,Tyrantrum,,
|
|
||||||
245,Amaura,,
|
|
||||||
246,Aurorus,,
|
|
||||||
247,Larvitar,,
|
|
||||||
248,Pupitar,,
|
|
||||||
249,Tyranitar,,
|
|
||||||
250,Phantump,,
|
|
||||||
251,Trevenant,,
|
|
||||||
252,Natu,,
|
|
||||||
253,Xatu,,
|
|
||||||
254,Nosepass,,
|
|
||||||
255,Probopass,,
|
|
||||||
256,Pyukumuku,,
|
|
||||||
257,Chinchou,,
|
|
||||||
258,Lanturn,,
|
|
||||||
259,Type: Null,,
|
|
||||||
260,Silvally,,
|
|
||||||
261,Poipole,,
|
|
||||||
262,Naganadel,,
|
|
||||||
263,Zygarde,,
|
|
||||||
264,Trubbish,,
|
|
||||||
265,Garbodor,,
|
|
||||||
266,Minccino,,
|
|
||||||
267,Cinccino,,
|
|
||||||
268,Pineco,,
|
|
||||||
269,Forretress,,
|
|
||||||
270,Skarmory,,
|
|
||||||
271,Ditto,,
|
|
||||||
272,Cleffa,,
|
|
||||||
273,Clefairy,,
|
|
||||||
274,Clefable,,
|
|
||||||
275,Elgyem,,
|
|
||||||
276,Beheeyem,,
|
|
||||||
277,Minior,,
|
|
||||||
278,Beldum,,
|
|
||||||
279,Metang,,
|
|
||||||
280,Metagross,,
|
|
||||||
281,Porygon,,
|
|
||||||
282,Porygon2,,
|
|
||||||
283,Porygon-Z,,
|
|
||||||
284,Pancham,,
|
|
||||||
285,Pangoro,,
|
|
||||||
286,Komala,,
|
|
||||||
287,Torkoal,,
|
|
||||||
288,Turtonator,,
|
|
||||||
289,Houndour,,
|
|
||||||
290,Houndoom,,
|
|
||||||
291,Dedenne,,
|
|
||||||
292,Togedemaru,,
|
|
||||||
293,Electrike,,
|
|
||||||
294,Manectric,,
|
|
||||||
295,Elekid,,
|
|
||||||
296,Electabuzz,,
|
|
||||||
297,Electivire,,
|
|
||||||
298,Geodude,,
|
|
||||||
299,Graveler,,
|
|
||||||
300,Golem,,
|
|
||||||
301,Sandile,,
|
|
||||||
302,Krokorok,,
|
|
||||||
303,Krookodile,,
|
|
||||||
304,Trapinch,,
|
|
||||||
305,Vibrava,,
|
|
||||||
306,Flygon,,
|
|
||||||
307,Gible,,
|
|
||||||
308,Gabite,,
|
|
||||||
309,Garchomp,,
|
|
||||||
310,Baltoy,,
|
|
||||||
311,Claydol,,
|
|
||||||
312,Golett,,
|
|
||||||
313,Golurk,,
|
|
||||||
314,Klefki,,
|
|
||||||
315,Mimikyu,,
|
|
||||||
316,Shuppet,,
|
|
||||||
317,Banette,,
|
|
||||||
318,Frillish,,
|
|
||||||
319,Jellicent,,
|
|
||||||
320,Bruxish,,
|
|
||||||
321,Drampa,,
|
|
||||||
322,Absol,,
|
|
||||||
323,Snorunt,,
|
|
||||||
324,Glalie,,
|
|
||||||
325,Froslass,,
|
|
||||||
326,Sneasel,,
|
|
||||||
327,Weavile,,
|
|
||||||
328,Sandshrew,,
|
|
||||||
329,Sandslash,,
|
|
||||||
330,Vulpix,,
|
|
||||||
331,Ninetales,,
|
|
||||||
332,Vanillite,,
|
|
||||||
333,Vanillish,,
|
|
||||||
334,Vanilluxe,,
|
|
||||||
335,Scraggy,,
|
|
||||||
336,Scrafty,,
|
|
||||||
337,Pawniard,,
|
|
||||||
338,Bisharp,,
|
|
||||||
339,Snubbull,,
|
|
||||||
340,Granbull,,
|
|
||||||
341,Shellos,,
|
|
||||||
342,Gastrodon,,
|
|
||||||
343,Relicanth,,
|
|
||||||
344,Dhelmise,,
|
|
||||||
345,Carvanha,,
|
|
||||||
346,Sharpedo,,
|
|
||||||
347,Skrelp,,
|
|
||||||
348,Dragalge,,
|
|
||||||
349,Clauncher,,
|
|
||||||
350,Clawitzer,,
|
|
||||||
351,Wailmer,,
|
|
||||||
352,Wailord,,
|
|
||||||
353,Lapras,,
|
|
||||||
354,Tropius,,
|
|
||||||
355,Exeggcute,,
|
|
||||||
356,Exeggutor,,
|
|
||||||
357,Corphish,,
|
|
||||||
358,Crawdaunt,,
|
|
||||||
359,Mienfoo,,
|
|
||||||
360,Mienshao,,
|
|
||||||
361,Jangmo-o,,
|
|
||||||
362,Hakamo-o,,
|
|
||||||
363,Kommo-o,,
|
|
||||||
364,Emolga,,
|
|
||||||
365,Scyther,,
|
|
||||||
366,Scizor,,
|
|
||||||
367,Heracross,,
|
|
||||||
368,Aipom,,
|
|
||||||
369,Ambipom,,
|
|
||||||
370,Litleo,,
|
|
||||||
371,Pyroar,,
|
|
||||||
372,Misdreavus,,
|
|
||||||
373,Mismagius,,
|
|
||||||
374,Druddigon,,
|
|
||||||
375,Lickitung,,
|
|
||||||
376,Lickilicky,,
|
|
||||||
377,Riolu,,
|
|
||||||
378,Lucario,,
|
|
||||||
379,Dratini,,
|
|
||||||
380,Dragonair,,
|
|
||||||
381,Dragonite,,
|
|
||||||
382,Aerodactyl,,
|
|
||||||
383,Tapu Koko,,
|
|
||||||
384,Tapu Lele,,
|
|
||||||
385,Tapu Bulu,,
|
|
||||||
386,Tapu Fini,,
|
|
||||||
387,Cosmog,,
|
|
||||||
388,Cosmoem,,
|
|
||||||
389,Solgaleo,,
|
|
||||||
390,Lunala,,
|
|
||||||
391,Stakataka,,
|
|
||||||
392,Blacephalon,,
|
|
||||||
393,Nihilego,,
|
|
||||||
394,Buzzwole,,
|
|
||||||
395,Pheromosa,,
|
|
||||||
396,Xurkitree,,
|
|
||||||
397,Celesteela,,
|
|
||||||
398,Kartana,,
|
|
||||||
399,Guzzlord,,
|
|
||||||
400,Necrozma,,
|
|
||||||
401,Magearna,,
|
|
||||||
402,Marshadow,,
|
|
||||||
403,Zeraora,,
|
|
||||||
|
@@ -1,151 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Rowlet,,
|
|
||||||
2,Dartrix,,
|
|
||||||
3,Decidueye,,
|
|
||||||
4,Litten,,
|
|
||||||
5,Torracat,,
|
|
||||||
6,Incineroar,,
|
|
||||||
7,Popplio,,
|
|
||||||
8,Brionne,,
|
|
||||||
9,Primarina,,
|
|
||||||
10,Pikipek,,
|
|
||||||
11,Trumbeak,,
|
|
||||||
12,Toucannon,,
|
|
||||||
13,Yungoos,,
|
|
||||||
14,Gumshoos,,
|
|
||||||
15,Rattata,,
|
|
||||||
16,Raticate,,
|
|
||||||
17,Caterpie,,
|
|
||||||
18,Metapod,,
|
|
||||||
19,Butterfree,,
|
|
||||||
20,Ledyba,,
|
|
||||||
21,Ledian,,
|
|
||||||
22,Spinarak,,
|
|
||||||
23,Ariados,,
|
|
||||||
24,Buneary,,
|
|
||||||
25,Lopunny,,
|
|
||||||
26,Inkay,,
|
|
||||||
27,Malamar,,
|
|
||||||
28,Zorua,,
|
|
||||||
29,Zoroark,,
|
|
||||||
30,Furfrou,,
|
|
||||||
31,Pichu,,
|
|
||||||
32,Pikachu,,
|
|
||||||
33,Raichu,,
|
|
||||||
34,Grubbin,,
|
|
||||||
35,Charjabug,,
|
|
||||||
36,Vikavolt,,
|
|
||||||
37,Bonsly,,
|
|
||||||
38,Sudowoodo,,
|
|
||||||
39,Happiny,,
|
|
||||||
40,Chansey,,
|
|
||||||
41,Blissey,,
|
|
||||||
42,Munchlax,,
|
|
||||||
43,Snorlax,,
|
|
||||||
44,Slowpoke,,
|
|
||||||
45,Slowbro,,
|
|
||||||
46,Slowking,,
|
|
||||||
47,Wingull,,
|
|
||||||
48,Pelipper,,
|
|
||||||
49,Abra,,
|
|
||||||
50,Kadabra,,
|
|
||||||
51,Alakazam,,
|
|
||||||
52,Meowth,,
|
|
||||||
53,Persian,,
|
|
||||||
54,Magnemite,,
|
|
||||||
55,Magneton,,
|
|
||||||
56,Magnezone,,
|
|
||||||
57,Grimer,,
|
|
||||||
58,Muk,,
|
|
||||||
59,Mime Jr.,,
|
|
||||||
60,Mr. Mime,,
|
|
||||||
61,Ekans,,
|
|
||||||
62,Arbok,,
|
|
||||||
63,Dunsparce,,
|
|
||||||
64,Growlithe,,
|
|
||||||
65,Arcanine,,
|
|
||||||
66,Drowzee,,
|
|
||||||
67,Hypno,,
|
|
||||||
68,Makuhita,,
|
|
||||||
69,Hariyama,,
|
|
||||||
70,Smeargle,,
|
|
||||||
71,Crabrawler,,
|
|
||||||
72,Crabominable,,
|
|
||||||
73,Gastly,,
|
|
||||||
74,Haunter,,
|
|
||||||
75,Gengar,,
|
|
||||||
76,Drifloon,,
|
|
||||||
77,Drifblim,,
|
|
||||||
78,Murkrow,,
|
|
||||||
79,Honchkrow,,
|
|
||||||
80,Zubat,,
|
|
||||||
81,Golbat,,
|
|
||||||
82,Crobat,,
|
|
||||||
83,Noibat,,
|
|
||||||
84,Noivern,,
|
|
||||||
85,Diglett,,
|
|
||||||
86,Dugtrio,,
|
|
||||||
87,Spearow,,
|
|
||||||
88,Fearow,,
|
|
||||||
89,Rufflet,,
|
|
||||||
90,Braviary,,
|
|
||||||
91,Vullaby,,
|
|
||||||
92,Mandibuzz,,
|
|
||||||
93,Mankey,,
|
|
||||||
94,Primeape,,
|
|
||||||
95,Delibird,,
|
|
||||||
96,Hawlucha,,
|
|
||||||
97,Oricorio,,
|
|
||||||
98,Cutiefly,,
|
|
||||||
99,Ribombee,,
|
|
||||||
100,Flabébé,,
|
|
||||||
101,Floette,,
|
|
||||||
102,Florges,,
|
|
||||||
103,Petilil,,
|
|
||||||
104,Lilligant,,
|
|
||||||
105,Cottonee,,
|
|
||||||
106,Whimsicott,,
|
|
||||||
107,Psyduck,,
|
|
||||||
108,Golduck,,
|
|
||||||
109,Smoochum,,
|
|
||||||
110,Jynx,,
|
|
||||||
111,Magikarp,,
|
|
||||||
112,Gyarados,,
|
|
||||||
113,Barboach,,
|
|
||||||
114,Whiscash,,
|
|
||||||
115,Seel,,
|
|
||||||
116,Dewgong,,
|
|
||||||
117,Machop,,
|
|
||||||
118,Machoke,,
|
|
||||||
119,Machamp,,
|
|
||||||
120,Roggenrola,,
|
|
||||||
121,Boldore,,
|
|
||||||
122,Gigalith,,
|
|
||||||
123,Carbink,,
|
|
||||||
124,Sableye,,
|
|
||||||
125,Mawile,,
|
|
||||||
126,Rockruff,,
|
|
||||||
127,Lycanroc,,
|
|
||||||
128,Spinda,,
|
|
||||||
129,Tentacool,,
|
|
||||||
130,Tentacruel,,
|
|
||||||
131,Finneon,,
|
|
||||||
132,Lumineon,,
|
|
||||||
133,Wishiwashi,,
|
|
||||||
134,Luvdisc,,
|
|
||||||
135,Corsola,,
|
|
||||||
136,Mareanie,,
|
|
||||||
137,Toxapex,,
|
|
||||||
138,Shellder,,
|
|
||||||
139,Cloyster,,
|
|
||||||
140,Clamperl,,
|
|
||||||
141,Huntail,,
|
|
||||||
142,Gorebyss,,
|
|
||||||
143,Remoraid,,
|
|
||||||
144,Octillery,,
|
|
||||||
145,Mantyke,,
|
|
||||||
146,Mantine,,
|
|
||||||
147,Bagon,,
|
|
||||||
148,Shelgon,,
|
|
||||||
149,Salamence,,
|
|
||||||
150,Tapu Koko,,
|
|
||||||
|
@@ -1,131 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Pikipek,,
|
|
||||||
2,Trumbeak,,
|
|
||||||
3,Toucannon,,
|
|
||||||
4,Yungoos,,
|
|
||||||
5,Gumshoos,,
|
|
||||||
6,Rattata,,
|
|
||||||
7,Raticate,,
|
|
||||||
8,Buneary,,
|
|
||||||
9,Lopunny,,
|
|
||||||
10,Inkay,,
|
|
||||||
11,Malamar,,
|
|
||||||
12,Zorua,,
|
|
||||||
13,Zoroark,,
|
|
||||||
14,Furfrou,,
|
|
||||||
15,Happiny,,
|
|
||||||
16,Chansey,,
|
|
||||||
17,Blissey,,
|
|
||||||
18,Wingull,,
|
|
||||||
19,Pelipper,,
|
|
||||||
20,Drowzee,,
|
|
||||||
21,Hypno,,
|
|
||||||
22,Makuhita,,
|
|
||||||
23,Hariyama,,
|
|
||||||
24,Crabrawler,,
|
|
||||||
25,Crabominable,,
|
|
||||||
26,Zubat,,
|
|
||||||
27,Golbat,,
|
|
||||||
28,Crobat,,
|
|
||||||
29,Noibat,,
|
|
||||||
30,Noivern,,
|
|
||||||
31,Diglett,,
|
|
||||||
32,Dugtrio,,
|
|
||||||
33,Spearow,,
|
|
||||||
34,Fearow,,
|
|
||||||
35,Rufflet,,
|
|
||||||
36,Braviary,,
|
|
||||||
37,Vullaby,,
|
|
||||||
38,Mandibuzz,,
|
|
||||||
39,Mankey,,
|
|
||||||
40,Primeape,,
|
|
||||||
41,Oricorio,,
|
|
||||||
42,Cutiefly,,
|
|
||||||
43,Ribombee,,
|
|
||||||
44,Flabébé,,
|
|
||||||
45,Floette,,
|
|
||||||
46,Florges,,
|
|
||||||
47,Petilil,,
|
|
||||||
48,Lilligant,,
|
|
||||||
49,Cottonee,,
|
|
||||||
50,Whimsicott,,
|
|
||||||
51,Psyduck,,
|
|
||||||
52,Golduck,,
|
|
||||||
53,Magikarp,,
|
|
||||||
54,Gyarados,,
|
|
||||||
55,Barboach,,
|
|
||||||
56,Whiscash,,
|
|
||||||
57,Machop,,
|
|
||||||
58,Machoke,,
|
|
||||||
59,Machamp,,
|
|
||||||
60,Roggenrola,,
|
|
||||||
61,Boldore,,
|
|
||||||
62,Gigalith,,
|
|
||||||
63,Carbink,,
|
|
||||||
64,Sableye,,
|
|
||||||
65,Rockruff,,
|
|
||||||
66,Lycanroc,,
|
|
||||||
67,Tentacool,,
|
|
||||||
68,Tentacruel,,
|
|
||||||
69,Finneon,,
|
|
||||||
70,Lumineon,,
|
|
||||||
71,Mudbray,,
|
|
||||||
72,Mudsdale,,
|
|
||||||
73,Tauros,,
|
|
||||||
74,Miltank,,
|
|
||||||
75,Basculin,,
|
|
||||||
76,Stufful,,
|
|
||||||
77,Bewear,,
|
|
||||||
78,Pinsir,,
|
|
||||||
79,Goomy,,
|
|
||||||
80,Sliggoo,,
|
|
||||||
81,Goodra,,
|
|
||||||
82,Castform,,
|
|
||||||
83,Wimpod,,
|
|
||||||
84,Golisopod,,
|
|
||||||
85,Skarmory,,
|
|
||||||
86,Snubbull,,
|
|
||||||
87,Granbull,,
|
|
||||||
88,Shellos,,
|
|
||||||
89,Gastrodon,,
|
|
||||||
90,Relicanth,,
|
|
||||||
91,Dhelmise,,
|
|
||||||
92,Carvanha,,
|
|
||||||
93,Sharpedo,,
|
|
||||||
94,Skrelp,,
|
|
||||||
95,Dragalge,,
|
|
||||||
96,Clauncher,,
|
|
||||||
97,Clawitzer,,
|
|
||||||
98,Wailmer,,
|
|
||||||
99,Wailord,,
|
|
||||||
100,Lapras,,
|
|
||||||
101,Tropius,,
|
|
||||||
102,Exeggcute,,
|
|
||||||
103,Exeggutor,,
|
|
||||||
104,Corphish,,
|
|
||||||
105,Crawdaunt,,
|
|
||||||
106,Mienfoo,,
|
|
||||||
107,Mienshao,,
|
|
||||||
108,Jangmo-o,,
|
|
||||||
109,Hakamo-o,,
|
|
||||||
110,Kommo-o,,
|
|
||||||
111,Emolga,,
|
|
||||||
112,Scyther,,
|
|
||||||
113,Scizor,,
|
|
||||||
114,Heracross,,
|
|
||||||
115,Aipom,,
|
|
||||||
116,Ambipom,,
|
|
||||||
117,Litleo,,
|
|
||||||
118,Pyroar,,
|
|
||||||
119,Misdreavus,,
|
|
||||||
120,Mismagius,,
|
|
||||||
121,Druddigon,,
|
|
||||||
122,Lickitung,,
|
|
||||||
123,Lickilicky,,
|
|
||||||
124,Riolu,,
|
|
||||||
125,Lucario,,
|
|
||||||
126,Dratini,,
|
|
||||||
127,Dragonair,,
|
|
||||||
128,Dragonite,,
|
|
||||||
129,Aerodactyl,,
|
|
||||||
130,Tapu Fini,,
|
|
||||||
|
@@ -1,161 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Pikipek,,
|
|
||||||
2,Trumbeak,,
|
|
||||||
3,Toucannon,,
|
|
||||||
4,Yungoos,,
|
|
||||||
5,Gumshoos,,
|
|
||||||
6,Rattata,,
|
|
||||||
7,Raticate,,
|
|
||||||
8,Ledyba,,
|
|
||||||
9,Ledian,,
|
|
||||||
10,Spinarak,,
|
|
||||||
11,Ariados,,
|
|
||||||
12,Grubbin,,
|
|
||||||
13,Charjabug,,
|
|
||||||
14,Vikavolt,,
|
|
||||||
15,Happiny,,
|
|
||||||
16,Chansey,,
|
|
||||||
17,Blissey,,
|
|
||||||
18,Slowpoke,,
|
|
||||||
19,Slowbro,,
|
|
||||||
20,Slowking,,
|
|
||||||
21,Wingull,,
|
|
||||||
22,Pelipper,,
|
|
||||||
23,Meowth,,
|
|
||||||
24,Persian,,
|
|
||||||
25,Magnemite,,
|
|
||||||
26,Magneton,,
|
|
||||||
27,Magnezone,,
|
|
||||||
28,Grimer,,
|
|
||||||
29,Muk,,
|
|
||||||
30,Crabrawler,,
|
|
||||||
31,Crabominable,,
|
|
||||||
32,Gastly,,
|
|
||||||
33,Haunter,,
|
|
||||||
34,Gengar,,
|
|
||||||
35,Zubat,,
|
|
||||||
36,Golbat,,
|
|
||||||
37,Crobat,,
|
|
||||||
38,Diglett,,
|
|
||||||
39,Dugtrio,,
|
|
||||||
40,Spearow,,
|
|
||||||
41,Fearow,,
|
|
||||||
42,Oricorio,,
|
|
||||||
43,Cutiefly,,
|
|
||||||
44,Ribombee,,
|
|
||||||
45,Flabébé,,
|
|
||||||
46,Floette,,
|
|
||||||
47,Florges,,
|
|
||||||
48,Petilil,,
|
|
||||||
49,Lilligant,,
|
|
||||||
50,Cottonee,,
|
|
||||||
51,Whimsicott,,
|
|
||||||
52,Psyduck,,
|
|
||||||
53,Golduck,,
|
|
||||||
54,Magikarp,,
|
|
||||||
55,Gyarados,,
|
|
||||||
56,Tentacool,,
|
|
||||||
57,Tentacruel,,
|
|
||||||
58,Finneon,,
|
|
||||||
59,Lumineon,,
|
|
||||||
60,Wishiwashi,,
|
|
||||||
61,Clamperl,,
|
|
||||||
62,Huntail,,
|
|
||||||
63,Gorebyss,,
|
|
||||||
64,Mudbray,,
|
|
||||||
65,Mudsdale,,
|
|
||||||
66,Surskit,,
|
|
||||||
67,Masquerain,,
|
|
||||||
68,Dewpider,,
|
|
||||||
69,Araquanid,,
|
|
||||||
70,Morelull,,
|
|
||||||
71,Shiinotic,,
|
|
||||||
72,Paras,,
|
|
||||||
73,Parasect,,
|
|
||||||
74,Poliwag,,
|
|
||||||
75,Poliwhirl,,
|
|
||||||
76,Poliwrath,,
|
|
||||||
77,Politoed,,
|
|
||||||
78,Goldeen,,
|
|
||||||
79,Seaking,,
|
|
||||||
80,Basculin,,
|
|
||||||
81,Goomy,,
|
|
||||||
82,Sliggoo,,
|
|
||||||
83,Goodra,,
|
|
||||||
84,Castform,,
|
|
||||||
85,Trubbish,,
|
|
||||||
86,Garbodor,,
|
|
||||||
87,Minccino,,
|
|
||||||
88,Cinccino,,
|
|
||||||
89,Pineco,,
|
|
||||||
90,Forretress,,
|
|
||||||
91,Skarmory,,
|
|
||||||
92,Ditto,,
|
|
||||||
93,Cleffa,,
|
|
||||||
94,Clefairy,,
|
|
||||||
95,Clefable,,
|
|
||||||
96,Elgyem,,
|
|
||||||
97,Beheeyem,,
|
|
||||||
98,Minior,,
|
|
||||||
99,Beldum,,
|
|
||||||
100,Metang,,
|
|
||||||
101,Metagross,,
|
|
||||||
102,Porygon,,
|
|
||||||
103,Porygon2,,
|
|
||||||
104,Porygon-Z,,
|
|
||||||
105,Pancham,,
|
|
||||||
106,Pangoro,,
|
|
||||||
107,Komala,,
|
|
||||||
108,Torkoal,,
|
|
||||||
109,Turtonator,,
|
|
||||||
110,Houndour,,
|
|
||||||
111,Houndoom,,
|
|
||||||
112,Dedenne,,
|
|
||||||
113,Togedemaru,,
|
|
||||||
114,Electrike,,
|
|
||||||
115,Manectric,,
|
|
||||||
116,Elekid,,
|
|
||||||
117,Electabuzz,,
|
|
||||||
118,Electivire,,
|
|
||||||
119,Geodude,,
|
|
||||||
120,Graveler,,
|
|
||||||
121,Golem,,
|
|
||||||
122,Sandile,,
|
|
||||||
123,Krokorok,,
|
|
||||||
124,Krookodile,,
|
|
||||||
125,Trapinch,,
|
|
||||||
126,Vibrava,,
|
|
||||||
127,Flygon,,
|
|
||||||
128,Gible,,
|
|
||||||
129,Gabite,,
|
|
||||||
130,Garchomp,,
|
|
||||||
131,Baltoy,,
|
|
||||||
132,Claydol,,
|
|
||||||
133,Golett,,
|
|
||||||
134,Golurk,,
|
|
||||||
135,Klefki,,
|
|
||||||
136,Mimikyu,,
|
|
||||||
137,Shuppet,,
|
|
||||||
138,Banette,,
|
|
||||||
139,Frillish,,
|
|
||||||
140,Jellicent,,
|
|
||||||
141,Bruxish,,
|
|
||||||
142,Drampa,,
|
|
||||||
143,Absol,,
|
|
||||||
144,Snorunt,,
|
|
||||||
145,Glalie,,
|
|
||||||
146,Froslass,,
|
|
||||||
147,Sneasel,,
|
|
||||||
148,Weavile,,
|
|
||||||
149,Sandshrew,,
|
|
||||||
150,Sandslash,,
|
|
||||||
151,Vulpix,,
|
|
||||||
152,Ninetales,,
|
|
||||||
153,Vanillite,,
|
|
||||||
154,Vanillish,,
|
|
||||||
155,Vanilluxe,,
|
|
||||||
156,Scraggy,,
|
|
||||||
157,Scrafty,,
|
|
||||||
158,Pawniard,,
|
|
||||||
159,Bisharp,,
|
|
||||||
160,Tapu Bulu,,
|
|
||||||
|
@@ -1,154 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Chespin,,
|
|
||||||
2,Quilladin,,
|
|
||||||
3,Chesnaught,,
|
|
||||||
4,Fennekin,,
|
|
||||||
5,Braixen,,
|
|
||||||
6,Delphox,,
|
|
||||||
7,Froakie,,
|
|
||||||
8,Frogadier,,
|
|
||||||
9,Greninja,,
|
|
||||||
10,Bunnelby,,
|
|
||||||
11,Diggersby,,
|
|
||||||
12,Zigzagoon,,
|
|
||||||
13,Linoone,,
|
|
||||||
14,Fletchling,,
|
|
||||||
15,Fletchinder,,
|
|
||||||
16,Talonflame,,
|
|
||||||
17,Pidgey,,
|
|
||||||
18,Pidgeotto,,
|
|
||||||
19,Pidgeot,,
|
|
||||||
20,Scatterbug,,
|
|
||||||
21,Spewpa,,
|
|
||||||
22,Vivillon,,
|
|
||||||
23,Caterpie,,
|
|
||||||
24,Metapod,,
|
|
||||||
25,Butterfree,,
|
|
||||||
26,Weedle,,
|
|
||||||
27,Kakuna,,
|
|
||||||
28,Beedrill,,
|
|
||||||
29,Pansage,,
|
|
||||||
30,Simisage,,
|
|
||||||
31,Pansear,,
|
|
||||||
32,Simisear,,
|
|
||||||
33,Panpour,,
|
|
||||||
34,Simipour,,
|
|
||||||
35,Pichu,,
|
|
||||||
36,Pikachu,,
|
|
||||||
37,Raichu,,
|
|
||||||
38,Bidoof,,
|
|
||||||
39,Bibarel,,
|
|
||||||
40,Dunsparce,,
|
|
||||||
41,Azurill,,
|
|
||||||
42,Marill,,
|
|
||||||
43,Azumarill,,
|
|
||||||
44,Burmy,,
|
|
||||||
45,Wormadam,,
|
|
||||||
46,Mothim,,
|
|
||||||
47,Surskit,,
|
|
||||||
48,Masquerain,,
|
|
||||||
49,Magikarp,,
|
|
||||||
50,Gyarados,,
|
|
||||||
51,Corphish,,
|
|
||||||
52,Crawdaunt,,
|
|
||||||
53,Goldeen,,
|
|
||||||
54,Seaking,,
|
|
||||||
55,Carvanha,,
|
|
||||||
56,Sharpedo,,
|
|
||||||
57,Litleo,,
|
|
||||||
58,Pyroar,,
|
|
||||||
59,Psyduck,,
|
|
||||||
60,Golduck,,
|
|
||||||
61,Farfetch'd,,
|
|
||||||
62,Riolu,,
|
|
||||||
63,Lucario,,
|
|
||||||
64,Ralts,,
|
|
||||||
65,Kirlia,,
|
|
||||||
66,Gardevoir,,
|
|
||||||
67,Gallade,,
|
|
||||||
68,Flabébé,,
|
|
||||||
69,Floette,,
|
|
||||||
70,Florges,,
|
|
||||||
71,Budew,,
|
|
||||||
72,Roselia,,
|
|
||||||
73,Roserade,,
|
|
||||||
74,Ledyba,,
|
|
||||||
75,Ledian,,
|
|
||||||
76,Combee,,
|
|
||||||
77,Vespiquen,,
|
|
||||||
78,Skitty,,
|
|
||||||
79,Delcatty,,
|
|
||||||
80,Bulbasaur,,
|
|
||||||
81,Ivysaur,,
|
|
||||||
82,Venusaur,,
|
|
||||||
83,Charmander,,
|
|
||||||
84,Charmeleon,,
|
|
||||||
85,Charizard,,
|
|
||||||
86,Squirtle,,
|
|
||||||
87,Wartortle,,
|
|
||||||
88,Blastoise,,
|
|
||||||
89,Skiddo,,
|
|
||||||
90,Gogoat,,
|
|
||||||
91,Pancham,,
|
|
||||||
92,Pangoro,,
|
|
||||||
93,Furfrou,,
|
|
||||||
94,Doduo,,
|
|
||||||
95,Dodrio,,
|
|
||||||
96,Plusle,,
|
|
||||||
97,Minun,,
|
|
||||||
98,Gulpin,,
|
|
||||||
99,Swalot,,
|
|
||||||
100,Scraggy,,
|
|
||||||
101,Scrafty,,
|
|
||||||
102,Abra,,
|
|
||||||
103,Kadabra,,
|
|
||||||
104,Alakazam,,
|
|
||||||
105,Oddish,,
|
|
||||||
106,Gloom,,
|
|
||||||
107,Vileplume,,
|
|
||||||
108,Bellossom,,
|
|
||||||
109,Sentret,,
|
|
||||||
110,Furret,,
|
|
||||||
111,Nincada,,
|
|
||||||
112,Ninjask,,
|
|
||||||
113,Shedinja,,
|
|
||||||
114,Espurr,,
|
|
||||||
115,Meowstic,,
|
|
||||||
116,Kecleon,,
|
|
||||||
117,Honedge,,
|
|
||||||
118,Doublade,,
|
|
||||||
119,Aegislash,,
|
|
||||||
120,Venipede,,
|
|
||||||
121,Whirlipede,,
|
|
||||||
122,Scolipede,,
|
|
||||||
123,Audino,,
|
|
||||||
124,Smeargle,,
|
|
||||||
125,Croagunk,,
|
|
||||||
126,Toxicroak,,
|
|
||||||
127,Ducklett,,
|
|
||||||
128,Swanna,,
|
|
||||||
129,Spritzee,,
|
|
||||||
130,Aromatisse,,
|
|
||||||
131,Swirlix,,
|
|
||||||
132,Slurpuff,,
|
|
||||||
133,Volbeat,,
|
|
||||||
134,Illumise,,
|
|
||||||
135,Hoppip,,
|
|
||||||
136,Skiploom,,
|
|
||||||
137,Jumpluff,,
|
|
||||||
138,Munchlax,,
|
|
||||||
139,Snorlax,,
|
|
||||||
140,Whismur,,
|
|
||||||
141,Loudred,,
|
|
||||||
142,Exploud,,
|
|
||||||
143,Meditite,,
|
|
||||||
144,Medicham,,
|
|
||||||
145,Zubat,,
|
|
||||||
146,Golbat,,
|
|
||||||
147,Crobat,,
|
|
||||||
148,Axew,,
|
|
||||||
149,Fraxure,,
|
|
||||||
150,Haxorus,,
|
|
||||||
151,Diancie,,
|
|
||||||
152,Hoopa,,
|
|
||||||
153,Volcanion,,
|
|
||||||
|
@@ -1,154 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Drifloon,,
|
|
||||||
2,Drifblim,,
|
|
||||||
3,Mienfoo,,
|
|
||||||
4,Mienshao,,
|
|
||||||
5,Zangoose,,
|
|
||||||
6,Seviper,,
|
|
||||||
7,Spoink,,
|
|
||||||
8,Grumpig,,
|
|
||||||
9,Absol,,
|
|
||||||
10,Inkay,,
|
|
||||||
11,Malamar,,
|
|
||||||
12,Lunatone,,
|
|
||||||
13,Solrock,,
|
|
||||||
14,Bagon,,
|
|
||||||
15,Shelgon,,
|
|
||||||
16,Salamence,,
|
|
||||||
17,Wingull,,
|
|
||||||
18,Pelipper,,
|
|
||||||
19,Taillow,,
|
|
||||||
20,Swellow,,
|
|
||||||
21,Binacle,,
|
|
||||||
22,Barbaracle,,
|
|
||||||
23,Dwebble,,
|
|
||||||
24,Crustle,,
|
|
||||||
25,Tentacool,,
|
|
||||||
26,Tentacruel,,
|
|
||||||
27,Wailmer,,
|
|
||||||
28,Wailord,,
|
|
||||||
29,Luvdisc,,
|
|
||||||
30,Skrelp,,
|
|
||||||
31,Dragalge,,
|
|
||||||
32,Clauncher,,
|
|
||||||
33,Clawitzer,,
|
|
||||||
34,Staryu,,
|
|
||||||
35,Starmie,,
|
|
||||||
36,Shellder,,
|
|
||||||
37,Cloyster,,
|
|
||||||
38,Qwilfish,,
|
|
||||||
39,Horsea,,
|
|
||||||
40,Seadra,,
|
|
||||||
41,Kingdra,,
|
|
||||||
42,Relicanth,,
|
|
||||||
43,Sandile,,
|
|
||||||
44,Krokorok,,
|
|
||||||
45,Krookodile,,
|
|
||||||
46,Helioptile,,
|
|
||||||
47,Heliolisk,,
|
|
||||||
48,Hippopotas,,
|
|
||||||
49,Hippowdon,,
|
|
||||||
50,Rhyhorn,,
|
|
||||||
51,Rhydon,,
|
|
||||||
52,Rhyperior,,
|
|
||||||
53,Onix,,
|
|
||||||
54,Steelix,,
|
|
||||||
55,Woobat,,
|
|
||||||
56,Swoobat,,
|
|
||||||
57,Machop,,
|
|
||||||
58,Machoke,,
|
|
||||||
59,Machamp,,
|
|
||||||
60,Cubone,,
|
|
||||||
61,Marowak,,
|
|
||||||
62,Kangaskhan,,
|
|
||||||
63,Mawile,,
|
|
||||||
64,Tyrunt,,
|
|
||||||
65,Tyrantrum,,
|
|
||||||
66,Amaura,,
|
|
||||||
67,Aurorus,,
|
|
||||||
68,Aerodactyl,,
|
|
||||||
69,Ferroseed,,
|
|
||||||
70,Ferrothorn,,
|
|
||||||
71,Snubbull,,
|
|
||||||
72,Granbull,,
|
|
||||||
73,Electrike,,
|
|
||||||
74,Manectric,,
|
|
||||||
75,Houndour,,
|
|
||||||
76,Houndoom,,
|
|
||||||
77,Eevee,,
|
|
||||||
78,Vaporeon,,
|
|
||||||
79,Jolteon,,
|
|
||||||
80,Flareon,,
|
|
||||||
81,Espeon,,
|
|
||||||
82,Umbreon,,
|
|
||||||
83,Leafeon,,
|
|
||||||
84,Glaceon,,
|
|
||||||
85,Sylveon,,
|
|
||||||
86,Emolga,,
|
|
||||||
87,Yanma,,
|
|
||||||
88,Yanmega,,
|
|
||||||
89,Hawlucha,,
|
|
||||||
90,Sigilyph,,
|
|
||||||
91,Golett,,
|
|
||||||
92,Golurk,,
|
|
||||||
93,Nosepass,,
|
|
||||||
94,Probopass,,
|
|
||||||
95,Makuhita,,
|
|
||||||
96,Hariyama,,
|
|
||||||
97,Throh,,
|
|
||||||
98,Sawk,,
|
|
||||||
99,Starly,,
|
|
||||||
100,Staravia,,
|
|
||||||
101,Staraptor,,
|
|
||||||
102,Stunky,,
|
|
||||||
103,Skuntank,,
|
|
||||||
104,Nidoran♀,,
|
|
||||||
105,Nidorina,,
|
|
||||||
106,Nidoqueen,,
|
|
||||||
107,Nidoran♂,,
|
|
||||||
108,Nidorino,,
|
|
||||||
109,Nidoking,,
|
|
||||||
110,Dedenne,,
|
|
||||||
111,Chingling,,
|
|
||||||
112,Chimecho,,
|
|
||||||
113,Mime Jr.,,
|
|
||||||
114,Mr. Mime,,
|
|
||||||
115,Solosis,,
|
|
||||||
116,Duosion,,
|
|
||||||
117,Reuniclus,,
|
|
||||||
118,Wynaut,,
|
|
||||||
119,Wobbuffet,,
|
|
||||||
120,Roggenrola,,
|
|
||||||
121,Boldore,,
|
|
||||||
122,Gigalith,,
|
|
||||||
123,Sableye,,
|
|
||||||
124,Carbink,,
|
|
||||||
125,Tauros,,
|
|
||||||
126,Miltank,,
|
|
||||||
127,Mareep,,
|
|
||||||
128,Flaaffy,,
|
|
||||||
129,Ampharos,,
|
|
||||||
130,Pinsir,,
|
|
||||||
131,Heracross,,
|
|
||||||
132,Pachirisu,,
|
|
||||||
133,Slowpoke,,
|
|
||||||
134,Slowbro,,
|
|
||||||
135,Slowking,,
|
|
||||||
136,Exeggcute,,
|
|
||||||
137,Exeggutor,,
|
|
||||||
138,Chatot,,
|
|
||||||
139,Mantyke,,
|
|
||||||
140,Mantine,,
|
|
||||||
141,Clamperl,,
|
|
||||||
142,Huntail,,
|
|
||||||
143,Gorebyss,,
|
|
||||||
144,Remoraid,,
|
|
||||||
145,Octillery,,
|
|
||||||
146,Corsola,,
|
|
||||||
147,Chinchou,,
|
|
||||||
148,Lanturn,,
|
|
||||||
149,Alomomola,,
|
|
||||||
150,Lapras,,
|
|
||||||
151,Articuno,,
|
|
||||||
152,Zapdos,,
|
|
||||||
153,Moltres,,
|
|
||||||
|
@@ -1,152 +0,0 @@
|
|||||||
dexNumber,pokemon,form,notes
|
|
||||||
1,Diglett,,
|
|
||||||
2,Dugtrio,,
|
|
||||||
3,Trapinch,,
|
|
||||||
4,Vibrava,,
|
|
||||||
5,Flygon,,
|
|
||||||
6,Gible,,
|
|
||||||
7,Gabite,,
|
|
||||||
8,Garchomp,,
|
|
||||||
9,Geodude,,
|
|
||||||
10,Graveler,,
|
|
||||||
11,Golem,,
|
|
||||||
12,Slugma,,
|
|
||||||
13,Magcargo,,
|
|
||||||
14,Shuckle,,
|
|
||||||
15,Skorupi,,
|
|
||||||
16,Drapion,,
|
|
||||||
17,Wooper,,
|
|
||||||
18,Quagsire,,
|
|
||||||
19,Goomy,,
|
|
||||||
20,Sliggoo,,
|
|
||||||
21,Goodra,,
|
|
||||||
22,Karrablast,,
|
|
||||||
23,Escavalier,,
|
|
||||||
24,Shelmet,,
|
|
||||||
25,Accelgor,,
|
|
||||||
26,Bellsprout,,
|
|
||||||
27,Weepinbell,,
|
|
||||||
28,Victreebel,,
|
|
||||||
29,Carnivine,,
|
|
||||||
30,Gastly,,
|
|
||||||
31,Haunter,,
|
|
||||||
32,Gengar,,
|
|
||||||
33,Poliwag,,
|
|
||||||
34,Poliwhirl,,
|
|
||||||
35,Poliwrath,,
|
|
||||||
36,Politoed,,
|
|
||||||
37,Ekans,,
|
|
||||||
38,Arbok,,
|
|
||||||
39,Stunfisk,,
|
|
||||||
40,Barboach,,
|
|
||||||
41,Whiscash,,
|
|
||||||
42,Purrloin,,
|
|
||||||
43,Liepard,,
|
|
||||||
44,Poochyena,,
|
|
||||||
45,Mightyena,,
|
|
||||||
46,Patrat,,
|
|
||||||
47,Watchog,,
|
|
||||||
48,Pawniard,,
|
|
||||||
49,Bisharp,,
|
|
||||||
50,Klefki,,
|
|
||||||
51,Murkrow,,
|
|
||||||
52,Honchkrow,,
|
|
||||||
53,Foongus,,
|
|
||||||
54,Amoonguss,,
|
|
||||||
55,Lotad,,
|
|
||||||
56,Lombre,,
|
|
||||||
57,Ludicolo,,
|
|
||||||
58,Buizel,,
|
|
||||||
59,Floatzel,,
|
|
||||||
60,Basculin,,
|
|
||||||
61,Phantump,,
|
|
||||||
62,Trevenant,,
|
|
||||||
63,Pumpkaboo,,
|
|
||||||
64,Gourgeist,,
|
|
||||||
65,Litwick,,
|
|
||||||
66,Lampent,,
|
|
||||||
67,Chandelure,,
|
|
||||||
68,Rotom,,
|
|
||||||
69,Magnemite,,
|
|
||||||
70,Magneton,,
|
|
||||||
71,Magnezone,,
|
|
||||||
72,Voltorb,,
|
|
||||||
73,Electrode,,
|
|
||||||
74,Trubbish,,
|
|
||||||
75,Garbodor,,
|
|
||||||
76,Swinub,,
|
|
||||||
77,Piloswine,,
|
|
||||||
78,Mamoswine,,
|
|
||||||
79,Bergmite,,
|
|
||||||
80,Avalugg,,
|
|
||||||
81,Cubchoo,,
|
|
||||||
82,Beartic,,
|
|
||||||
83,Smoochum,,
|
|
||||||
84,Jynx,,
|
|
||||||
85,Vanillite,,
|
|
||||||
86,Vanillish,,
|
|
||||||
87,Vanilluxe,,
|
|
||||||
88,Snover,,
|
|
||||||
89,Abomasnow,,
|
|
||||||
90,Delibird,,
|
|
||||||
91,Sneasel,,
|
|
||||||
92,Weavile,,
|
|
||||||
93,Timburr,,
|
|
||||||
94,Gurdurr,,
|
|
||||||
95,Conkeldurr,,
|
|
||||||
96,Torkoal,,
|
|
||||||
97,Sandshrew,,
|
|
||||||
98,Sandslash,,
|
|
||||||
99,Aron,,
|
|
||||||
100,Lairon,,
|
|
||||||
101,Aggron,,
|
|
||||||
102,Larvitar,,
|
|
||||||
103,Pupitar,,
|
|
||||||
104,Tyranitar,,
|
|
||||||
105,Heatmor,,
|
|
||||||
106,Durant,,
|
|
||||||
107,Spinarak,,
|
|
||||||
108,Ariados,,
|
|
||||||
109,Spearow,,
|
|
||||||
110,Fearow,,
|
|
||||||
111,Cryogonal,,
|
|
||||||
112,Skarmory,,
|
|
||||||
113,Noibat,,
|
|
||||||
114,Noivern,,
|
|
||||||
115,Gligar,,
|
|
||||||
116,Gliscor,,
|
|
||||||
117,Hoothoot,,
|
|
||||||
118,Noctowl,,
|
|
||||||
119,Igglybuff,,
|
|
||||||
120,Jigglypuff,,
|
|
||||||
121,Wigglytuff,,
|
|
||||||
122,Shuppet,,
|
|
||||||
123,Banette,,
|
|
||||||
124,Zorua,,
|
|
||||||
125,Zoroark,,
|
|
||||||
126,Gothita,,
|
|
||||||
127,Gothorita,,
|
|
||||||
128,Gothitelle,,
|
|
||||||
129,Bonsly,,
|
|
||||||
130,Sudowoodo,,
|
|
||||||
131,Spinda,,
|
|
||||||
132,Teddiursa,,
|
|
||||||
133,Ursaring,,
|
|
||||||
134,Lickitung,,
|
|
||||||
135,Lickilicky,,
|
|
||||||
136,Scyther,,
|
|
||||||
137,Scizor,,
|
|
||||||
138,Ditto,,
|
|
||||||
139,Swablu,,
|
|
||||||
140,Altaria,,
|
|
||||||
141,Druddigon,,
|
|
||||||
142,Deino,,
|
|
||||||
143,Zweilous,,
|
|
||||||
144,Hydreigon,,
|
|
||||||
145,Dratini,,
|
|
||||||
146,Dragonair,,
|
|
||||||
147,Dragonite,,
|
|
||||||
148,Xerneas,,
|
|
||||||
149,Yveltal,,
|
|
||||||
150,Zygarde,,
|
|
||||||
151,Mewtwo,,
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,15 +0,0 @@
|
|||||||
region,releaseOrder
|
|
||||||
Kanto,1
|
|
||||||
Johto,2
|
|
||||||
Hoenn,3
|
|
||||||
Orre,4
|
|
||||||
Sinnoh,5
|
|
||||||
Ranch,6
|
|
||||||
Unova,7
|
|
||||||
Kalos,8
|
|
||||||
Alola,9
|
|
||||||
Go,10
|
|
||||||
Galar,11
|
|
||||||
Home,12
|
|
||||||
Hisui,13
|
|
||||||
Paldea,14
|
|
||||||
|
+1
-7
@@ -1,9 +1,3 @@
|
|||||||
[build]
|
[build]
|
||||||
command = "npm ci && ./node_modules/.bin/supabase link --project-ref $SUPABASE_PROJECT_REF && ./node_modules/.bin/supabase db push && npm run build"
|
command = "npm run build"
|
||||||
publish = "build"
|
publish = "build"
|
||||||
|
|
||||||
[build.environment]
|
|
||||||
NODE_VERSION = "22"
|
|
||||||
|
|
||||||
[context.deploy-preview]
|
|
||||||
command = "npm ci && npm run build"
|
|
||||||
|
|||||||
Generated
+1018
-1853
File diff suppressed because it is too large
Load Diff
+4
-13
@@ -1,12 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "livingdextracker",
|
"name": "LivingDexTracker",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
|
"dev": "npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
|
||||||
"dev-generate": "GENERATE_SW=true npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
|
"dev-generate": "GENERATE_SW=true npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
|
||||||
"dev-generate-suppress-w": "GENERATE_SW=true SUPPRESS_WARNING=true npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
|
"dev-generate-suppress-w": "GENERATE_SW=true SUPPRESS_WARNING=true npx tailwindcss -i ./static/input.css -o ./static/output.css && vite dev",
|
||||||
"sprites:build": "node scripts/optimize-sprites.mjs",
|
|
||||||
"build-generate-sw": "GENERATE_SW=true vite build",
|
"build-generate-sw": "GENERATE_SW=true vite build",
|
||||||
"build-generate-sw-node": "NODE_ADAPTER=true GENERATE_SW=true vite build",
|
"build-generate-sw-node": "NODE_ADAPTER=true GENERATE_SW=true vite build",
|
||||||
"build": "npx tailwindcss -i ./static/input.css -o ./static/output.css && vite build",
|
"build": "npx tailwindcss -i ./static/input.css -o ./static/output.css && vite build",
|
||||||
@@ -24,14 +23,7 @@
|
|||||||
"test-generate-sw-node": "npm run build-generate-sw-node && NODE_ADAPTER=true GENERATE_SW=true vitest run && NODE_ADAPTER=true GENERATE_SW=true playwright test",
|
"test-generate-sw-node": "npm run build-generate-sw-node && NODE_ADAPTER=true GENERATE_SW=true vitest run && NODE_ADAPTER=true GENERATE_SW=true playwright test",
|
||||||
"test-inject-manifest": "npm run build-inject-manifest && vitest run && playwright test",
|
"test-inject-manifest": "npm run build-inject-manifest && vitest run && playwright test",
|
||||||
"test-inject-manifest-node": "npm run build-inject-manifest-node && NODE_ADAPTER=true vitest run && NODE_ADAPTER=true playwright test",
|
"test-inject-manifest-node": "npm run build-inject-manifest-node && NODE_ADAPTER=true vitest run && NODE_ADAPTER=true playwright test",
|
||||||
"test": "npm run test-generate-sw && npm run test-generate-sw-node && npm run test-inject-manifest && npm run test-inject-manifest-node",
|
"test": "npm run test-generate-sw && npm run test-generate-sw-node && npm run test-inject-manifest && npm run test-inject-manifest-node"
|
||||||
"supabase:start": "supabase start",
|
|
||||||
"supabase:stop": "supabase stop",
|
|
||||||
"supabase:reset": "supabase db reset",
|
|
||||||
"supabase:studio": "supabase studio",
|
|
||||||
"migrate:convert-tsv": "node scripts/convert-tsv-to-sql.js",
|
|
||||||
"dev:local": "./scripts/dev-local.sh && npm run dev",
|
|
||||||
"dev:supabase": "supabase start && npm run dev"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.37.1",
|
"@playwright/test": "^1.37.1",
|
||||||
@@ -39,7 +31,7 @@
|
|||||||
"@sveltejs/adapter-netlify": "^4.1.0",
|
"@sveltejs/adapter-netlify": "^4.1.0",
|
||||||
"@sveltejs/adapter-node": "^2.0.0",
|
"@sveltejs/adapter-node": "^2.0.0",
|
||||||
"@sveltejs/adapter-static": "^3.0.0",
|
"@sveltejs/adapter-static": "^3.0.0",
|
||||||
"@sveltejs/kit": "^2.5.3",
|
"@sveltejs/kit": "^2.0.6",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
"@types/cookie": "^0.6.0",
|
"@types/cookie": "^0.6.0",
|
||||||
"@types/eslint": "^8.56.0",
|
"@types/eslint": "^8.56.0",
|
||||||
@@ -55,8 +47,6 @@
|
|||||||
"postcss": "^8.4.38",
|
"postcss": "^8.4.38",
|
||||||
"prettier": "^3.1.1",
|
"prettier": "^3.1.1",
|
||||||
"prettier-plugin-svelte": "^3.1.2",
|
"prettier-plugin-svelte": "^3.1.2",
|
||||||
"sharp": "^0.33.4",
|
|
||||||
"supabase": "2.72.7",
|
|
||||||
"svelte": "^4.2.8",
|
"svelte": "^4.2.8",
|
||||||
"svelte-check": "^3.6.2",
|
"svelte-check": "^3.6.2",
|
||||||
"tailwindcss": "^3.4.3",
|
"tailwindcss": "^3.4.3",
|
||||||
@@ -68,6 +58,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@supabase/ssr": "^0.1.0",
|
"@supabase/ssr": "^0.1.0",
|
||||||
"@supabase/supabase-js": "^2.42.0",
|
"@supabase/supabase-js": "^2.42.0",
|
||||||
|
"mongoose": "^8.0.3",
|
||||||
"nanoid": "^5.0.4"
|
"nanoid": "^5.0.4"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|||||||
Generated
-7717
File diff suppressed because it is too large
Load Diff
@@ -1,183 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates SQL migration from CSV files
|
|
||||||
* Usage: node csv-to-migration.js <Region>
|
|
||||||
* Example: node csv-to-migration.js Kanto
|
|
||||||
*/
|
|
||||||
|
|
||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
|
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
|
||||||
const __dirname = path.dirname(__filename);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse CSV file into array of objects
|
|
||||||
*/
|
|
||||||
function parseCSV(filePath) {
|
|
||||||
const content = fs.readFileSync(filePath, 'utf-8');
|
|
||||||
const lines = content.split('\n').filter(line => line.trim());
|
|
||||||
const headers = lines[0].split(',');
|
|
||||||
|
|
||||||
return lines.slice(1).map(line => {
|
|
||||||
const values = parseCSVLine(line);
|
|
||||||
const obj = {};
|
|
||||||
headers.forEach((header, i) => {
|
|
||||||
obj[header] = values[i] || null;
|
|
||||||
});
|
|
||||||
return obj;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse a single CSV line, handling quoted values
|
|
||||||
*/
|
|
||||||
function parseCSVLine(line) {
|
|
||||||
const values = [];
|
|
||||||
let current = '';
|
|
||||||
let inQuotes = false;
|
|
||||||
|
|
||||||
for (let i = 0; i < line.length; i++) {
|
|
||||||
const char = line[i];
|
|
||||||
|
|
||||||
if (char === '"') {
|
|
||||||
inQuotes = !inQuotes;
|
|
||||||
} else if (char === ',' && !inQuotes) {
|
|
||||||
values.push(current);
|
|
||||||
current = '';
|
|
||||||
} else {
|
|
||||||
current += char;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
values.push(current);
|
|
||||||
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate migration SQL from CSV data
|
|
||||||
*/
|
|
||||||
function generateMigration(region) {
|
|
||||||
console.log(`\nGenerating migration for ${region}...`);
|
|
||||||
|
|
||||||
// Determine generation number from region
|
|
||||||
const regionToGen = {
|
|
||||||
'Kanto': 1, 'Johto': 2, 'Hoenn': 3, 'Sinnoh': 4,
|
|
||||||
'Unova': 5, 'Kalos': 6, 'Alola': 7, 'Galar': 8,
|
|
||||||
'Hisui': 8, 'Paldea': 9
|
|
||||||
};
|
|
||||||
const gen = regionToGen[region] || 1;
|
|
||||||
|
|
||||||
// 1. Load CSV files
|
|
||||||
const pokemonPath = path.join(__dirname, '..', 'data', 'pokemon', `gen${gen}-${region.toLowerCase()}.csv`);
|
|
||||||
const gamesPath = path.join(__dirname, '..', 'data', 'pokemon', 'games.csv');
|
|
||||||
|
|
||||||
if (!fs.existsSync(pokemonPath)) {
|
|
||||||
console.error(`Error: Pokemon CSV not found at ${pokemonPath}`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const pokemon = parseCSV(pokemonPath);
|
|
||||||
const games = parseCSV(gamesPath);
|
|
||||||
|
|
||||||
// 2. Filter for this region
|
|
||||||
const regionGames = games.filter(g => g.region === region);
|
|
||||||
|
|
||||||
if (regionGames.length === 0) {
|
|
||||||
console.error(`Error: No games found for region ${region} in games.csv`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Generate SQL
|
|
||||||
let sql = `-- Seed ${region} region Pokémon (Gen ${gen})\n`;
|
|
||||||
sql += `-- Auto-generated from CSV files\n\n`;
|
|
||||||
|
|
||||||
// Region-game mappings
|
|
||||||
sql += `-- Insert ${region} region-game mappings\n`;
|
|
||||||
sql += `INSERT INTO region_game_mappings (region, game) VALUES\n`;
|
|
||||||
sql += regionGames.map(g => ` ('${region}', '${g.displayName}')`).join(',\n');
|
|
||||||
sql += `\nON CONFLICT (region, game) DO NOTHING;\n\n`;
|
|
||||||
|
|
||||||
// Pokemon entries (without regional dex number)
|
|
||||||
sql += `-- Insert ${region} Pokémon entries\n`;
|
|
||||||
sql += `INSERT INTO pokedex_entries (\n`;
|
|
||||||
sql += ` "pokedexNumber",\n`;
|
|
||||||
sql += ` pokemon,\n`;
|
|
||||||
sql += ` form,\n`;
|
|
||||||
sql += ` "canGigantamax",\n`;
|
|
||||||
sql += ` "regionToCatchIn",\n`;
|
|
||||||
sql += ` "gamesToCatchIn"\n`;
|
|
||||||
sql += `) VALUES\n`;
|
|
||||||
|
|
||||||
const rows = pokemon.map(p => {
|
|
||||||
const form = p.form ? `'${p.form}'` : 'NULL';
|
|
||||||
// Use regionalDexGames for the database (regional dex availability)
|
|
||||||
// originGames column is for future origin dex feature
|
|
||||||
const gamesField = p.regionalDexGames || p.games; // Fallback to old 'games' column for compatibility
|
|
||||||
const gamesList = gamesField.split('|');
|
|
||||||
const gamesArray = `ARRAY[${gamesList.map(g => `'${g}'`).join(', ')}]`;
|
|
||||||
|
|
||||||
return `(${p.pokedexNumber}, '${p.name}', ${form}, false, '${region}', ${gamesArray})`;
|
|
||||||
});
|
|
||||||
|
|
||||||
sql += rows.join(',\n');
|
|
||||||
sql += '\nON CONFLICT ON CONSTRAINT unique_pokemon_form DO NOTHING;\n\n';
|
|
||||||
|
|
||||||
// Regional dex numbers (separate table)
|
|
||||||
sql += `-- Insert ${region} regional dex numbers\n`;
|
|
||||||
|
|
||||||
const dexRows = pokemon
|
|
||||||
.filter(p => p.regionalNumber) // Only entries with regional dex numbers
|
|
||||||
.map(p => {
|
|
||||||
const formCondition = p.form
|
|
||||||
? `form = '${p.form}'`
|
|
||||||
: `form IS NULL`;
|
|
||||||
|
|
||||||
return ` ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = ${p.pokedexNumber} AND ${formCondition}), '${region}', ${p.regionalNumber})`;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (dexRows.length > 0) {
|
|
||||||
sql += `INSERT INTO regional_dex_numbers (\n`;
|
|
||||||
sql += ` pokedex_entry_id,\n`;
|
|
||||||
sql += ` region,\n`;
|
|
||||||
sql += ` dex_number\n`;
|
|
||||||
sql += `) VALUES\n`;
|
|
||||||
sql += dexRows.join(',\n');
|
|
||||||
sql += ';\n\n';
|
|
||||||
} else {
|
|
||||||
sql += '-- No regional dex numbers for this region\n\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add metadata
|
|
||||||
sql += `-- Add metadata\n`;
|
|
||||||
sql += `INSERT INTO metadata (key, value) VALUES\n`;
|
|
||||||
sql += ` ('${region.toLowerCase()}_seeded', 'true'),\n`;
|
|
||||||
sql += ` ('${region.toLowerCase()}_seed_date', NOW()::TEXT),\n`;
|
|
||||||
sql += ` ('${region.toLowerCase()}_pokemon_count', '${pokemon.filter(p => !p.form).length}');\n`;
|
|
||||||
|
|
||||||
// 4. Write file
|
|
||||||
const timestamp = new Date().toISOString().replace(/[-:T.]/g, '').slice(0, 14);
|
|
||||||
const filename = `${timestamp}_seed_${region.toLowerCase()}.sql`;
|
|
||||||
const outputPath = path.join(__dirname, '..', 'supabase', 'migrations', filename);
|
|
||||||
|
|
||||||
fs.writeFileSync(outputPath, sql);
|
|
||||||
|
|
||||||
console.log(`✓ Generated ${filename}`);
|
|
||||||
console.log(` - ${pokemon.length} Pokemon entries`);
|
|
||||||
console.log(` - ${dexRows.length} regional dex numbers`);
|
|
||||||
console.log(` - ${regionGames.length} games\n`);
|
|
||||||
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run
|
|
||||||
const region = process.argv[2];
|
|
||||||
if (!region) {
|
|
||||||
console.error('Usage: node csv-to-migration.js <Region>');
|
|
||||||
console.error('Example: node csv-to-migration.js Kanto');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
generateMigration(region);
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#!/usr/bin/env node
|
|
||||||
import path from 'node:path';
|
|
||||||
import process from 'node:process';
|
|
||||||
import { mkdir, readdir, rename } from 'node:fs/promises';
|
|
||||||
import sharp from 'sharp';
|
|
||||||
|
|
||||||
const inputDir = process.env.SPRITE_INPUT_DIR ?? path.join(process.cwd(), 'static', 'sprites');
|
|
||||||
const outputDir =
|
|
||||||
process.env.SPRITE_OUTPUT_DIR ?? path.join(process.cwd(), 'static', 'sprites-small');
|
|
||||||
const format = (process.env.SPRITE_FORMAT ?? 'webp').toLowerCase();
|
|
||||||
const quality = Number(process.env.SPRITE_QUALITY ?? 80);
|
|
||||||
const maxSize = Number(process.env.SPRITE_MAX_SIZE ?? 0);
|
|
||||||
|
|
||||||
if (!['png', 'webp'].includes(format)) {
|
|
||||||
console.error(`Unsupported SPRITE_FORMAT "${format}". Use "png" or "webp".`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function walk(dir, files = []) {
|
|
||||||
const entries = await readdir(dir, { withFileTypes: true });
|
|
||||||
for (const entry of entries) {
|
|
||||||
const fullPath = path.join(dir, entry.name);
|
|
||||||
if (entry.isDirectory()) {
|
|
||||||
await walk(fullPath, files);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (entry.isFile() && entry.name.toLowerCase().endsWith('.png')) {
|
|
||||||
files.push(fullPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files;
|
|
||||||
}
|
|
||||||
|
|
||||||
const files = await walk(inputDir);
|
|
||||||
console.log(`Optimizing ${files.length} sprite images from ${inputDir}`);
|
|
||||||
|
|
||||||
for (const [index, file] of files.entries()) {
|
|
||||||
const relative = path.relative(inputDir, file);
|
|
||||||
const baseName = path.basename(file, path.extname(file));
|
|
||||||
const targetDir = path.join(outputDir, path.dirname(relative));
|
|
||||||
await mkdir(targetDir, { recursive: true });
|
|
||||||
|
|
||||||
const targetExt = format === 'png' ? '.png' : '.webp';
|
|
||||||
const targetPath = path.join(targetDir, `${baseName}${targetExt}`);
|
|
||||||
const tempPath = format === 'png' && outputDir === inputDir ? `${targetPath}.tmp` : targetPath;
|
|
||||||
|
|
||||||
const pipeline = sharp(file);
|
|
||||||
if (maxSize > 0) {
|
|
||||||
pipeline.resize({
|
|
||||||
width: maxSize,
|
|
||||||
height: maxSize,
|
|
||||||
fit: 'inside',
|
|
||||||
withoutEnlargement: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format === 'png') {
|
|
||||||
await pipeline.png({ compressionLevel: 9, palette: true, quality }).toFile(tempPath);
|
|
||||||
} else {
|
|
||||||
await pipeline.webp({ quality }).toFile(tempPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tempPath !== targetPath) {
|
|
||||||
await rename(tempPath, targetPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((index + 1) % 250 === 0) {
|
|
||||||
console.log(`Processed ${index + 1}/${files.length}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log('Sprite optimization complete.');
|
|
||||||
Vendored
+1
-6
@@ -1,7 +1,6 @@
|
|||||||
import 'vite-plugin-pwa/svelte';
|
import 'vite-plugin-pwa/svelte';
|
||||||
import 'vite-plugin-pwa/info';
|
import 'vite-plugin-pwa/info';
|
||||||
import 'vite-plugin-pwa/pwa-assets';
|
import 'vite-plugin-pwa/pwa-assets';
|
||||||
import { SupabaseClient, Session, User } from '@supabase/supabase-js';
|
|
||||||
|
|
||||||
// See https://kit.svelte.dev/docs/types#app
|
// See https://kit.svelte.dev/docs/types#app
|
||||||
// for information about these interfaces
|
// for information about these interfaces
|
||||||
@@ -12,16 +11,12 @@ declare global {
|
|||||||
namespace App {
|
namespace App {
|
||||||
// interface Error {}
|
// interface Error {}
|
||||||
interface Locals {
|
interface Locals {
|
||||||
supabase: SupabaseClient;
|
|
||||||
safeGetSession(): Promise<{ session: Session | null; user: User | null }>;
|
|
||||||
userid: string;
|
userid: string;
|
||||||
buildDate: string;
|
buildDate: string;
|
||||||
periodicUpdates: boolean;
|
periodicUpdates: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface PageData {
|
// interface PageData {}
|
||||||
session: Session | null;
|
|
||||||
}
|
|
||||||
// interface PageState {}
|
// interface PageState {}
|
||||||
// interface Platform {}
|
// interface Platform {}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-14
@@ -1,22 +1,9 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en" data-theme="pokeball">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<script>
|
|
||||||
(function () {
|
|
||||||
try {
|
|
||||||
const storedTheme = localStorage.getItem('theme');
|
|
||||||
const allowed = ['pokeball', 'dark'];
|
|
||||||
const theme = storedTheme && allowed.includes(storedTheme) ? storedTheme : 'pokeball';
|
|
||||||
document.documentElement.setAttribute('data-theme', theme);
|
|
||||||
} catch (e) {
|
|
||||||
// Fallback to default theme if localStorage is not accessible
|
|
||||||
document.documentElement.setAttribute('data-theme', 'pokeball');
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
</script>
|
|
||||||
%sveltekit.head%
|
%sveltekit.head%
|
||||||
<link rel="stylesheet" href="%sveltekit.assets%/output.css" />
|
<link rel="stylesheet" href="%sveltekit.assets%/output.css" />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -1,106 +0,0 @@
|
|||||||
type InViewParams = {
|
|
||||||
rootMargin?: string;
|
|
||||||
threshold?: number | number[];
|
|
||||||
once?: boolean;
|
|
||||||
enabled?: boolean;
|
|
||||||
onChange?: (inView: boolean, entry: IntersectionObserverEntry) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const observers = new Map<string, IntersectionObserver>();
|
|
||||||
const callbacks = new WeakMap<Element, (entry: IntersectionObserverEntry) => void>();
|
|
||||||
|
|
||||||
function normalizeThreshold(threshold: number | number[] | undefined) {
|
|
||||||
if (threshold === undefined) return [0];
|
|
||||||
return Array.isArray(threshold) ? threshold : [threshold];
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildObserverKey(rootMargin: string, threshold: number | number[]) {
|
|
||||||
return `${rootMargin}|${JSON.stringify(normalizeThreshold(threshold))}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getObserver(rootMargin: string, threshold: number | number[]) {
|
|
||||||
const key = buildObserverKey(rootMargin, threshold);
|
|
||||||
const existing = observers.get(key);
|
|
||||||
if (existing) return existing;
|
|
||||||
|
|
||||||
const observer = new IntersectionObserver(
|
|
||||||
(entries) => {
|
|
||||||
for (const entry of entries) {
|
|
||||||
const callback = callbacks.get(entry.target);
|
|
||||||
if (callback) {
|
|
||||||
callback(entry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ rootMargin, threshold }
|
|
||||||
);
|
|
||||||
observers.set(key, observer);
|
|
||||||
return observer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function inView(node: Element, params: InViewParams = {}) {
|
|
||||||
let options: Required<InViewParams> = {
|
|
||||||
rootMargin: '200px 0px',
|
|
||||||
threshold: 0,
|
|
||||||
once: true,
|
|
||||||
enabled: true,
|
|
||||||
onChange: () => undefined,
|
|
||||||
...params
|
|
||||||
};
|
|
||||||
|
|
||||||
let observer = getObserver(options.rootMargin, options.threshold);
|
|
||||||
|
|
||||||
const handleEntry = (entry: IntersectionObserverEntry) => {
|
|
||||||
const isIntersecting = entry.isIntersecting || entry.intersectionRatio > 0;
|
|
||||||
options.onChange(isIntersecting, entry);
|
|
||||||
if (isIntersecting && options.once) {
|
|
||||||
observer.unobserve(node);
|
|
||||||
callbacks.delete(node);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const startObserving = () => {
|
|
||||||
callbacks.set(node, handleEntry);
|
|
||||||
observer.observe(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
const stopObserving = () => {
|
|
||||||
observer.unobserve(node);
|
|
||||||
callbacks.delete(node);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (options.enabled) {
|
|
||||||
startObserving();
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
update(next: InViewParams = {}) {
|
|
||||||
const nextOptions: Required<InViewParams> = {
|
|
||||||
...options,
|
|
||||||
...next,
|
|
||||||
onChange: next.onChange ?? options.onChange
|
|
||||||
};
|
|
||||||
const observerKeyChanged =
|
|
||||||
buildObserverKey(options.rootMargin, options.threshold) !==
|
|
||||||
buildObserverKey(nextOptions.rootMargin, nextOptions.threshold);
|
|
||||||
const enabledChanged = options.enabled !== nextOptions.enabled;
|
|
||||||
|
|
||||||
if (observerKeyChanged || enabledChanged) {
|
|
||||||
stopObserving();
|
|
||||||
}
|
|
||||||
|
|
||||||
options = nextOptions;
|
|
||||||
|
|
||||||
if (observerKeyChanged) {
|
|
||||||
observer = getObserver(options.rootMargin, options.threshold);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.enabled) {
|
|
||||||
startObserving();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
destroy() {
|
|
||||||
stopObserving();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,106 +1,100 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
import pokeApiPokemon from '$lib/helpers/pokeapi-pokemon.json';
|
||||||
import { PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER } from '$env/static/public';
|
import { PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER } from '$env/static/public';
|
||||||
import { inView } from '$lib/actions/inView';
|
|
||||||
|
|
||||||
export let pokemonName: string;
|
export let pokemonName: string;
|
||||||
export let pokedexNumber: string | number;
|
export let pokedexNumber: string | number;
|
||||||
export let form: string | undefined;
|
export let form: string | undefined;
|
||||||
export let spriteKey: string | undefined;
|
|
||||||
export let shiny: boolean | undefined = false;
|
export let shiny: boolean | undefined = false;
|
||||||
export let loadingStrategy: 'eager' | 'lazy' | 'inView' = 'inView';
|
|
||||||
|
|
||||||
let imagePath = null as string | null;
|
let imagePath = null as string | null;
|
||||||
let isInView = false;
|
let blah = '';
|
||||||
|
|
||||||
function isFemaleForm(value?: string) {
|
function setImagePath() {
|
||||||
return /^female\b/i.test((value ?? '').trim());
|
let rootFolder =
|
||||||
}
|
|
||||||
|
|
||||||
function buildFallbackKey() {
|
|
||||||
const strippedPokedexNumber = pokedexNumber.toString().replace(/^0+/, '') || '0';
|
|
||||||
if (!form) return strippedPokedexNumber;
|
|
||||||
|
|
||||||
let formValue = form.trim();
|
|
||||||
formValue = formValue.replace(/^female[-\s]*/i, '');
|
|
||||||
formValue = formValue
|
|
||||||
.replace(/\s*\(.*?\)/g, '')
|
|
||||||
.replace(/\s*\[.*?\]/g, '')
|
|
||||||
.trim();
|
|
||||||
if (!formValue || formValue.toLowerCase() === 'male') return strippedPokedexNumber;
|
|
||||||
|
|
||||||
formValue = formValue
|
|
||||||
.toLowerCase()
|
|
||||||
.replace(/%/g, '')
|
|
||||||
.replace(/\balolan\b/g, 'alola')
|
|
||||||
.replace(/\bgalarian\b/g, 'galar')
|
|
||||||
.replace(/\bhisuian\b/g, 'hisui')
|
|
||||||
.replace(/\bpaldean\b/g, 'paldea')
|
|
||||||
.replace(/\bform(e)?$/, '')
|
|
||||||
.replace(/\bability$/, '')
|
|
||||||
.replace(/[^a-z0-9]+/g, '-')
|
|
||||||
.replace(/(^-|-$)/g, '')
|
|
||||||
.replace(/2/g, 'two')
|
|
||||||
.replace(/3/g, 'three')
|
|
||||||
.replace(/4/g, 'four');
|
|
||||||
|
|
||||||
return formValue ? `${strippedPokedexNumber}-${formValue}` : strippedPokedexNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
$: {
|
|
||||||
const rootFolderBase =
|
|
||||||
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER === 'true'
|
PUBLIC_USE_LOCAL_POKEMON_SPRITE_FOLDER === 'true'
|
||||||
? '/sprites-small/home'
|
? '/sprites/home'
|
||||||
: 'https://raw.githubusercontent.com/jcreek/LivingDexTracker/master/static/sprites-small/home';
|
: 'https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/other/home';
|
||||||
const resolvedSpriteKey = spriteKey?.trim() || buildFallbackKey();
|
|
||||||
if (!spriteKey?.trim()) {
|
if (form === 'Female') {
|
||||||
console.warn('Missing sprite key for pokemon entry', {
|
rootFolder += '/female';
|
||||||
pokemonName,
|
|
||||||
pokedexNumber,
|
|
||||||
form
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let rootFolder = rootFolderBase;
|
|
||||||
if (shiny) {
|
if (shiny) {
|
||||||
rootFolder += '/shiny';
|
rootFolder += '/shiny';
|
||||||
}
|
}
|
||||||
if (isFemaleForm(form)) {
|
|
||||||
rootFolder += '/female';
|
// Remove leading zeros
|
||||||
}
|
const strippedPokedexNumber = pokedexNumber.toString().replace(/^0+/, '');
|
||||||
imagePath = `${rootFolder}/${resolvedSpriteKey}.webp`;
|
|
||||||
|
// Sanitise the pokemon name by making it all lowercase and replacing any spaces with hyphens and removing other characters
|
||||||
|
let sanitisedPokemonName = pokemonName.toLowerCase().replace(/[^a-z]/g, '');
|
||||||
|
|
||||||
|
// Get the PokeApi id for the pokemon
|
||||||
|
let pokeApiId;
|
||||||
|
if (form && form.length > 0 && form !== 'Female') {
|
||||||
|
// Sanitise the form by making it all lowercase and replacing spaces with hyphens
|
||||||
|
let sanitisedForm = form
|
||||||
|
.toLowerCase()
|
||||||
|
.replaceAll(' ', '-')
|
||||||
|
.replaceAll('2', 'two')
|
||||||
|
.replaceAll('3', 'three')
|
||||||
|
.replaceAll('4', 'four');
|
||||||
|
|
||||||
|
switch (sanitisedForm) {
|
||||||
|
case 'alolan':
|
||||||
|
sanitisedForm = 'alola';
|
||||||
|
break;
|
||||||
|
case 'galarian':
|
||||||
|
sanitisedForm = 'galar';
|
||||||
|
break;
|
||||||
|
case 'hisuian':
|
||||||
|
sanitisedForm = 'hisui';
|
||||||
|
break;
|
||||||
|
// case 'rainbow-ribbon':
|
||||||
|
// sanitisedForm = 'rainbow-swirl-ribbon-sweet';
|
||||||
|
// break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
$: if (loadingStrategy !== 'inView') {
|
// if (strippedPokedexNumber == '869') {
|
||||||
isInView = true;
|
// console.log(sanitisedPokemonName, sanitisedForm);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// If the form is contained in the identifier, use that
|
||||||
|
if (
|
||||||
|
pokeApiPokemon.find(
|
||||||
|
(pokemon) => pokemon.identifier === sanitisedPokemonName + '-' + sanitisedForm
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
pokeApiId = pokeApiPokemon.find(
|
||||||
|
(pokemon) => pokemon.identifier === sanitisedPokemonName + '-' + sanitisedForm
|
||||||
|
)?.id;
|
||||||
|
} else {
|
||||||
|
// If the form is not contained in the identifier, use the species_id
|
||||||
|
pokeApiId = pokeApiPokemon.find(
|
||||||
|
(pokemon) => pokemon.species_id.toString() === strippedPokedexNumber
|
||||||
|
)?.id;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pokeApiId = pokeApiPokemon.find(
|
||||||
|
(pokemon) => pokemon.species_id.toString() === strippedPokedexNumber
|
||||||
|
)?.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleInView(inView: boolean) {
|
imagePath = `${rootFolder}/${pokeApiId}.png`;
|
||||||
if (inView) {
|
blah = `${pokeApiId}.png`;
|
||||||
isInView = true;
|
// blah = `${strippedPokedexNumber}${form?.length && form !== 'Female' ? '-' + form : ''}.png`;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(setImagePath);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if imagePath}
|
{#if imagePath}
|
||||||
<span
|
<!-- {blah} -->
|
||||||
use:inView={{
|
<img src={imagePath} alt="sprite" />
|
||||||
enabled: loadingStrategy === 'inView',
|
|
||||||
once: true,
|
|
||||||
rootMargin: '200px 0px',
|
|
||||||
onChange: handleInView
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{#if loadingStrategy === 'inView' && !isInView}
|
|
||||||
<span class="loading loading-spinner loading-xs"></span>
|
|
||||||
{:else}
|
|
||||||
<img
|
|
||||||
src={imagePath}
|
|
||||||
alt="sprite"
|
|
||||||
loading={loadingStrategy === 'lazy' ? 'lazy' : 'eager'}
|
|
||||||
decoding="async"
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
{:else}
|
{:else}
|
||||||
<span class="loading loading-spinner loading-xs"></span>
|
<span class="loading loading-spinner loading-xs"></span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -8,141 +8,49 @@
|
|||||||
|
|
||||||
let email = '';
|
let email = '';
|
||||||
let password = '';
|
let password = '';
|
||||||
let isLoading = false;
|
|
||||||
let errorMessage = '';
|
|
||||||
|
|
||||||
// Access the supabase client from the layout data
|
// Access the supabase client from the layout data
|
||||||
export let supabase: any;
|
export let supabase: any;
|
||||||
|
|
||||||
async function signInWithEmail() {
|
async function signInWithEmail() {
|
||||||
isLoading = true;
|
// TODO use the data and error from the response
|
||||||
errorMessage = '';
|
const { data, error } = await supabase.auth
|
||||||
|
.signInWithPassword({
|
||||||
try {
|
|
||||||
const { data, error } = await supabase.auth.signInWithPassword({
|
|
||||||
email: email,
|
email: email,
|
||||||
password: password
|
password: password
|
||||||
});
|
})
|
||||||
|
.then(() => {
|
||||||
if (error) {
|
|
||||||
console.error('Sign in error:', error);
|
|
||||||
errorMessage = error.message;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
emitSignedInEvent();
|
emitSignedInEvent();
|
||||||
}
|
});
|
||||||
} catch (err) {
|
|
||||||
console.error('Sign in error:', err);
|
|
||||||
errorMessage = 'An unexpected error occurred. Please try again.';
|
|
||||||
} finally {
|
|
||||||
isLoading = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleKeyPress(event: KeyboardEvent) {
|
|
||||||
if (event.key === 'Enter') {
|
|
||||||
signInWithEmail();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="space-y-4">
|
<label class="input input-bordered flex items-center gap-2">
|
||||||
<!-- Error Message -->
|
|
||||||
{#if errorMessage}
|
|
||||||
<div class="alert alert-error text-sm">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5 shrink-0 stroke-current"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<span>{errorMessage}</span>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<!-- Email Input -->
|
|
||||||
<div class="form-control">
|
|
||||||
<label class="label" for="signin-email">
|
|
||||||
<span class="label-text font-medium">Email</span>
|
|
||||||
</label>
|
|
||||||
<div class="relative">
|
|
||||||
<input
|
|
||||||
id="signin-email"
|
|
||||||
type="email"
|
|
||||||
placeholder="your@email.com"
|
|
||||||
class="input input-bordered w-full pl-10"
|
|
||||||
bind:value={email}
|
|
||||||
on:keypress={handleKeyPress}
|
|
||||||
disabled={isLoading}
|
|
||||||
/>
|
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 16 16"
|
viewBox="0 0 16 16"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
class="h-4 w-4 opacity-70 absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none"
|
class="w-4 h-4 opacity-70"
|
||||||
>
|
><path
|
||||||
<path
|
|
||||||
d="M2.5 3A1.5 1.5 0 0 0 1 4.5v.793c.026.009.051.02.076.032L7.674 8.51c.206.1.446.1.652 0l6.598-3.185A.755.755 0 0 1 15 5.293V4.5A1.5 1.5 0 0 0 13.5 3h-11Z"
|
d="M2.5 3A1.5 1.5 0 0 0 1 4.5v.793c.026.009.051.02.076.032L7.674 8.51c.206.1.446.1.652 0l6.598-3.185A.755.755 0 0 1 15 5.293V4.5A1.5 1.5 0 0 0 13.5 3h-11Z"
|
||||||
/>
|
/><path
|
||||||
<path
|
|
||||||
d="M15 6.954 8.978 9.86a2.25 2.25 0 0 1-1.956 0L1 6.954V11.5A1.5 1.5 0 0 0 2.5 13h11a1.5 1.5 0 0 0 1.5-1.5V6.954Z"
|
d="M15 6.954 8.978 9.86a2.25 2.25 0 0 1-1.956 0L1 6.954V11.5A1.5 1.5 0 0 0 2.5 13h11a1.5 1.5 0 0 0 1.5-1.5V6.954Z"
|
||||||
/>
|
/></svg
|
||||||
</svg>
|
>
|
||||||
</div>
|
<input type="text" class="grow" placeholder="Email" bind:value={email} />
|
||||||
</div>
|
</label>
|
||||||
|
<label class="input input-bordered flex items-center gap-2">
|
||||||
<!-- Password Input -->
|
|
||||||
<div class="form-control">
|
|
||||||
<label class="label" for="signin-password">
|
|
||||||
<span class="label-text font-medium">Password</span>
|
|
||||||
</label>
|
|
||||||
<div class="relative">
|
|
||||||
<input
|
|
||||||
id="signin-password"
|
|
||||||
type="password"
|
|
||||||
placeholder="••••••••"
|
|
||||||
class="input input-bordered w-full pl-10"
|
|
||||||
bind:value={password}
|
|
||||||
on:keypress={handleKeyPress}
|
|
||||||
disabled={isLoading}
|
|
||||||
/>
|
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 16 16"
|
viewBox="0 0 16 16"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
class="h-4 w-4 opacity-70 absolute left-3 top-1/2 -translate-y-1/2 pointer-events-none"
|
class="w-4 h-4 opacity-70"
|
||||||
>
|
><path
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
fill-rule="evenodd"
|
||||||
d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2.293a.5.5 0 0 1 .146-.353l3.955-3.955A4 4 0 1 1 14 6Zm-4-2a.75.75 0 0 0 0 1.5.5.5 0 0 1 .5.5.75.75 0 0 0 1.5 0 2 2 0 0 0-2-2Z"
|
d="M14 6a4 4 0 0 1-4.899 3.899l-1.955 1.955a.5.5 0 0 1-.353.146H5v1.5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-2.293a.5.5 0 0 1 .146-.353l3.955-3.955A4 4 0 1 1 14 6Zm-4-2a.75.75 0 0 0 0 1.5.5.5 0 0 1 .5.5.75.75 0 0 0 1.5 0 2 2 0 0 0-2-2Z"
|
||||||
clip-rule="evenodd"
|
clip-rule="evenodd"
|
||||||
/>
|
/></svg
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Sign In Button -->
|
|
||||||
<div class="form-control mt-6">
|
|
||||||
<button
|
|
||||||
class="btn btn-primary w-full"
|
|
||||||
on:click={signInWithEmail}
|
|
||||||
disabled={isLoading || !email || !password}
|
|
||||||
>
|
>
|
||||||
{#if isLoading}
|
<input type="password" class="grow" placeholder="Password" bind:value={password} />
|
||||||
<span class="loading loading-spinner loading-sm"></span>
|
</label>
|
||||||
Signing in...
|
<button class="btn btn-active btn-primary" on:click={signInWithEmail}>Sign In</button>
|
||||||
{:else}
|
|
||||||
Sign In
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte';
|
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
|
|
||||||
let email = '';
|
let email = '';
|
||||||
let password = '';
|
let password = '';
|
||||||
|
|
||||||
@@ -20,29 +17,23 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
console.error('Sign up error:', error);
|
throw error;
|
||||||
alert(`Sign up failed: ${error.message}`);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data) {
|
// Handle success (optional)
|
||||||
// Emit signedUp event to notify parent component
|
} catch (error) {
|
||||||
dispatch('signedUp', {});
|
console.error('Sign up error:', error.message);
|
||||||
}
|
// Handle error
|
||||||
} catch (err) {
|
|
||||||
console.error('Sign up error:', err);
|
|
||||||
alert('Sign up failed');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<form class="card-body">
|
<form class="card-body">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label" for="signup-email">
|
<label class="label">
|
||||||
<span class="label-text">Email</span>
|
<span class="label-text">Email</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="signup-email"
|
|
||||||
type="email"
|
type="email"
|
||||||
placeholder="email"
|
placeholder="email"
|
||||||
class="input input-bordered"
|
class="input input-bordered"
|
||||||
@@ -51,11 +42,10 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="label" for="signup-password">
|
<label class="label">
|
||||||
<span class="label-text">Password</span>
|
<span class="label-text">Password</span>
|
||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
id="signup-password"
|
|
||||||
type="password"
|
type="password"
|
||||||
placeholder="password"
|
placeholder="password"
|
||||||
class="input input-bordered"
|
class="input input-bordered"
|
||||||
@@ -64,12 +54,6 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-control mt-6">
|
<div class="form-control mt-6">
|
||||||
<button class="btn btn-primary" on:click={signUpNewUser}>Sign Up</button>
|
<button class="btn btn btn-primary" on:click={signUpNewUser}>Sign Up</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
<style>
|
|
||||||
.card-body {
|
|
||||||
padding: 0.5rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { theme, applyTheme } from '$lib/stores/theme.js';
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
|
|
||||||
let currentTheme: 'pokeball' | 'dark' = 'pokeball';
|
|
||||||
|
|
||||||
// Subscribe to theme changes
|
|
||||||
$: (currentTheme = $theme), applyTheme($theme);
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
// Initialize theme from localStorage
|
|
||||||
theme.init();
|
|
||||||
});
|
|
||||||
|
|
||||||
function toggleTheme() {
|
|
||||||
theme.toggle();
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<button
|
|
||||||
class="btn btn-ghost btn-circle"
|
|
||||||
on:click={toggleTheme}
|
|
||||||
aria-label="Toggle dark mode"
|
|
||||||
title="Toggle dark mode"
|
|
||||||
>
|
|
||||||
{#if currentTheme === 'pokeball'}
|
|
||||||
<!-- Sun icon for light mode (clicking will switch to dark) -->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
{:else}
|
|
||||||
<!-- Moon icon for dark mode (clicking will switch to light) -->
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
@@ -7,16 +7,14 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="relative inline-block">
|
<div class="relative inline-block">
|
||||||
<button
|
<div
|
||||||
type="button"
|
class="tooltip-trigger cursor-pointer"
|
||||||
class="tooltip-trigger cursor-pointer bg-transparent border-0 p-0 appearance-none"
|
|
||||||
aria-expanded={show}
|
|
||||||
on:click={handleClick}
|
on:click={handleClick}
|
||||||
on:mouseenter={() => (show = true)}
|
on:mouseenter={() => (show = true)}
|
||||||
on:mouseleave={() => (show = false)}
|
on:mouseleave={() => (show = false)}
|
||||||
>
|
>
|
||||||
<slot name="hover-target" />
|
<slot name="hover-target" />
|
||||||
</button>
|
</div>
|
||||||
|
|
||||||
{#if show}
|
{#if show}
|
||||||
<div class="tooltip-content absolute z-10 mt-2 w-52">
|
<div class="tooltip-content absolute z-10 mt-2 w-52">
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import type { Pokedex } from '$lib/models/Pokedex';
|
|
||||||
|
|
||||||
export let pokedex: Pokedex;
|
|
||||||
export let onEdit: () => void;
|
|
||||||
export let onDelete: () => void;
|
|
||||||
export let onView: () => void;
|
|
||||||
|
|
||||||
// Get active type badges
|
|
||||||
$: typeBadges = [
|
|
||||||
pokedex.isLivingDex && 'Living',
|
|
||||||
pokedex.isShinyDex && 'Shiny',
|
|
||||||
pokedex.isOriginDex && 'Origin',
|
|
||||||
pokedex.isFormDex && 'Form'
|
|
||||||
].filter(Boolean);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="card bg-base-100 shadow-xl">
|
|
||||||
<div class="card-body">
|
|
||||||
<h2 class="card-title">
|
|
||||||
{pokedex.name}
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
{#if pokedex.description}
|
|
||||||
<p class="text-sm">{pokedex.description}</p>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="flex flex-wrap gap-2 my-2">
|
|
||||||
{#each typeBadges as badge}
|
|
||||||
<span class="badge badge-primary">{badge}</span>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if pokedex.gameScope}
|
|
||||||
<div class="text-sm text-base-content/70">
|
|
||||||
<span class="font-semibold">Game:</span>
|
|
||||||
{pokedex.gameScope}
|
|
||||||
</div>
|
|
||||||
{#if pokedex.dexScopes?.length}
|
|
||||||
<div class="text-sm text-base-content/70">
|
|
||||||
<span class="font-semibold">Dexes:</span>
|
|
||||||
{pokedex.dexScopes.length}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{:else}
|
|
||||||
<div class="text-sm text-base-content/70">
|
|
||||||
<span class="font-semibold">Scope:</span> All Games
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="card-actions justify-end mt-4">
|
|
||||||
<button class="btn btn-sm btn-ghost" on:click={onEdit}>Edit</button>
|
|
||||||
<button class="btn btn-sm btn-error btn-outline" on:click={onDelete}>Delete</button>
|
|
||||||
<button class="btn btn-sm btn-primary" on:click={onView}>View</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,62 +1,20 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { CatchRecord } from '$lib/models/CatchRecord';
|
import type { CatchRecord } from '$lib/models/CatchRecord';
|
||||||
import type { CatchInformationItem, PokedexEntry } from '$lib/models/PokedexEntry';
|
import type { PokedexEntry } from '$lib/models/PokedexEntry';
|
||||||
import PokemonSprite from '../PokemonSprite.svelte';
|
import PokemonSprite from '../PokemonSprite.svelte';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
|
|
||||||
export let pokedexEntry: PokedexEntry;
|
export let pokedexEntry: PokedexEntry;
|
||||||
export let catchRecord: CatchRecord | null;
|
export let catchRecord: CatchRecord;
|
||||||
export let showOrigins: boolean;
|
export let showOrigins: boolean;
|
||||||
export let showForms: boolean;
|
export let showForms: boolean;
|
||||||
export let showShiny: boolean;
|
export let showShiny: boolean;
|
||||||
export let userId: string | null = null;
|
|
||||||
export let pokedexId: string;
|
|
||||||
|
|
||||||
// Create a default catch record if none exists
|
|
||||||
$: if (!catchRecord) {
|
|
||||||
catchRecord = {
|
|
||||||
_id: '', // Empty string, not temp ID - will be created by server
|
|
||||||
userId: userId || '',
|
|
||||||
pokemonId: pokedexEntry._id,
|
|
||||||
pokedexId: pokedexId,
|
|
||||||
haveToEvolve: false,
|
|
||||||
caught: false,
|
|
||||||
inHome: false,
|
|
||||||
hasGigantamaxed: false,
|
|
||||||
personalNotes: ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
type UpdateCatchSource = 'toggle' | 'notes' | 'notes-blur';
|
function updateCatchRecord() {
|
||||||
|
dispatch('updateCatch', { pokedexEntry, catchRecord });
|
||||||
const isCatchInformationItem = (
|
|
||||||
value: string | CatchInformationItem
|
|
||||||
): value is CatchInformationItem => typeof value !== 'string';
|
|
||||||
|
|
||||||
function updateCatchRecord(source: UpdateCatchSource) {
|
|
||||||
dispatch('updateCatch', { pokedexEntry, catchRecord, source });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCaughtChange() {
|
|
||||||
if (!catchRecord) return;
|
|
||||||
// Mutually exclusive with "needs to evolve"
|
|
||||||
if (catchRecord.caught) {
|
|
||||||
catchRecord.haveToEvolve = false;
|
|
||||||
}
|
|
||||||
updateCatchRecord('toggle');
|
|
||||||
}
|
|
||||||
|
|
||||||
function onNeedsToEvolveChange() {
|
|
||||||
if (!catchRecord) return;
|
|
||||||
// Mutually exclusive with "caught"
|
|
||||||
if (catchRecord.haveToEvolve) {
|
|
||||||
catchRecord.caught = false;
|
|
||||||
}
|
|
||||||
updateCatchRecord('toggle');
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -64,42 +22,53 @@
|
|||||||
>
|
>
|
||||||
<div class="dex-column pokedex-entry-container">
|
<div class="dex-column pokedex-entry-container">
|
||||||
<div class="flex mb-2">
|
<div class="flex mb-2">
|
||||||
<div class="pl-2">
|
<div class="sprite-container flex justify-center items-center bg-white rounded-lg p-2">
|
||||||
<h3 class="text-xl font-bold pt-1">{pokedexEntry.pokemon}</h3>
|
|
||||||
<sub class="text-primary-content/80"
|
|
||||||
>#{pokedexEntry.pokedexNumber.toString().padStart(3, '0')}</sub
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex mb-2">
|
|
||||||
<div class="sprite-container flex justify-center items-center bg-base-100 rounded-lg p-2">
|
|
||||||
<PokemonSprite
|
<PokemonSprite
|
||||||
pokemonName={pokedexEntry.pokemon}
|
pokemonName={pokedexEntry.pokemon}
|
||||||
pokedexNumber={pokedexEntry.pokedexNumber}
|
pokedexNumber={pokedexEntry.pokedexNumber}
|
||||||
form={pokedexEntry.form}
|
form={pokedexEntry.form}
|
||||||
spriteKey={pokedexEntry.spriteKey}
|
|
||||||
shiny={showShiny}
|
shiny={showShiny}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pl-2">
|
||||||
|
<h3 class="text-xl font-bold pt-1 text-secondary">{pokedexEntry.pokemon}</h3>
|
||||||
|
<sub class="text-gray-200">#{pokedexEntry.pokedexNumber.toString().padStart(3, '0')}</sub>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if showForms}
|
{#if showForms}
|
||||||
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
|
<div class="bg-white text-black rounded-lg p-4 mb-2">
|
||||||
<p><strong>Form:</strong> {pokedexEntry.form ? pokedexEntry.form : '-'}</p>
|
<p><strong>Form:</strong> {pokedexEntry.form ? pokedexEntry.form : '-'}</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if pokedexEntry.evolutionInformation.trim().length > 0}
|
<div class="bg-white text-black rounded-lg p-4">
|
||||||
<div class="bg-base-100 text-base-content rounded-lg p-4">
|
{#if showForms}
|
||||||
|
<p><strong>Box:</strong> {pokedexEntry.boxPlacementForms.box}</p>
|
||||||
|
<p><strong>Row:</strong> {pokedexEntry.boxPlacementForms.row}</p>
|
||||||
|
<p><strong>Column:</strong> {pokedexEntry.boxPlacementForms.column}</p>
|
||||||
|
<p><strong>Can Gigantamax:</strong> {pokedexEntry.canGigantamax ? 'Yes' : 'No'}</p>
|
||||||
|
{:else}
|
||||||
|
<p><strong>Box:</strong> {pokedexEntry.boxPlacement.box}</p>
|
||||||
|
<p><strong>Row:</strong> {pokedexEntry.boxPlacement.row}</p>
|
||||||
|
<p><strong>Column:</strong> {pokedexEntry.boxPlacement.column}</p>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if pokedexEntry.evolutionInformation}
|
||||||
<p><strong>How to evolve: </strong>{pokedexEntry.evolutionInformation}</p>
|
<p><strong>How to evolve: </strong>{pokedexEntry.evolutionInformation}</p>
|
||||||
</div>
|
{:else}
|
||||||
|
<p>
|
||||||
|
<strong>How to evolve: </strong>Currently missing - can you
|
||||||
|
<a
|
||||||
|
href="https://github.com/jcreek/LivingDexTracker"
|
||||||
|
class="underline text-primary hover:text-secondary">help contribute</a
|
||||||
|
>?
|
||||||
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{#if catchRecord}
|
<div class="dex-column catch-record-container bg-white text-black rounded-lg p-4 mb-4 md:mb-0">
|
||||||
<div
|
|
||||||
class="dex-column catch-record-container bg-base-100 text-base-content rounded-lg p-4 mb-4 md:mb-0"
|
|
||||||
>
|
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="cursor-pointer label">
|
<label class="cursor-pointer label">
|
||||||
@@ -107,8 +76,8 @@
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
bind:checked={catchRecord.caught}
|
bind:checked={catchRecord.caught}
|
||||||
class="checkbox checkbox-primary"
|
class="checkbox checkbox-primary border-black"
|
||||||
on:change={onCaughtChange}
|
on:change={updateCatchRecord}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -120,8 +89,8 @@
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
bind:checked={catchRecord.haveToEvolve}
|
bind:checked={catchRecord.haveToEvolve}
|
||||||
class="checkbox checkbox-primary"
|
class="checkbox checkbox-primary border-black"
|
||||||
on:change={onNeedsToEvolveChange}
|
on:change={updateCatchRecord}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -129,12 +98,12 @@
|
|||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="form-control">
|
<div class="form-control">
|
||||||
<label class="cursor-pointer label">
|
<label class="cursor-pointer label">
|
||||||
<span class="block font-bold mr-2">In Home:</span>
|
<span class="block font-bold mr-2">In home:</span>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
bind:checked={catchRecord.inHome}
|
bind:checked={catchRecord.inHome}
|
||||||
class="checkbox checkbox-primary"
|
class="checkbox checkbox-primary border-black"
|
||||||
on:change={() => updateCatchRecord('toggle')}
|
on:change={updateCatchRecord}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -147,33 +116,29 @@
|
|||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
bind:checked={catchRecord.hasGigantamaxed}
|
bind:checked={catchRecord.hasGigantamaxed}
|
||||||
class="checkbox checkbox-primary"
|
class="checkbox checkbox-primary border-black"
|
||||||
on:change={() => updateCatchRecord('toggle')}
|
on:change={updateCatchRecord}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<p>
|
<p>
|
||||||
<label
|
<label class="block font-bold mb-1" for={`personalNotesInput-${catchRecord._id}`}
|
||||||
class="block font-bold mb-1"
|
>Notes:</label
|
||||||
for={`personalNotesInput-${catchRecord._id || pokedexEntry._id}`}>Notes:</label
|
|
||||||
>
|
>
|
||||||
<textarea
|
<textarea
|
||||||
bind:value={catchRecord.personalNotes}
|
bind:value={catchRecord.personalNotes}
|
||||||
id={`personalNotesInput-${catchRecord._id || pokedexEntry._id}`}
|
id={`personalNotesInput-${catchRecord._id}`}
|
||||||
class="textarea textarea-bordered w-full"
|
class="form-textarea w-full p-2 border rounded"
|
||||||
style="min-height: 120px;"
|
on:change={updateCatchRecord}
|
||||||
on:input={() => updateCatchRecord('notes')}
|
|
||||||
on:change={() => updateCatchRecord('notes-blur')}
|
|
||||||
></textarea>
|
></textarea>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="dex-column additional-details-container">
|
<div class="dex-column additional-details-container">
|
||||||
{#if showOrigins}
|
{#if showOrigins}
|
||||||
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
|
<div class="bg-white text-black rounded-lg p-4 mb-2">
|
||||||
<h3 class="text-xl font-semibold mb-4">Origin Dex Requirements</h3>
|
<h3 class="text-xl font-semibold mb-4">Origin Dex Requirements</h3>
|
||||||
<p><strong>Region to Catch In:</strong> {pokedexEntry.regionToCatchIn}</p>
|
<p><strong>Region to Catch In:</strong> {pokedexEntry.regionToCatchIn}</p>
|
||||||
<p><strong>Games to catch in:</strong></p>
|
<p><strong>Games to catch in:</strong></p>
|
||||||
@@ -188,20 +153,16 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if pokedexEntry.catchInformation.length > 0}
|
{#if pokedexEntry.catchInformation.length > 0}
|
||||||
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
|
<div class="bg-white text-black rounded-lg p-4 mb-2">
|
||||||
<p><strong>Where to catch: </strong></p>
|
<p><strong>Where to catch: </strong></p>
|
||||||
<ul class="list-disc list-inside">
|
<ul class="list-disc list-inside">
|
||||||
{#each pokedexEntry.catchInformation as info}
|
{#each pokedexEntry.catchInformation as info}
|
||||||
<li>
|
<li>
|
||||||
{#if isCatchInformationItem(info)}
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><strong>Game:</strong> {info.game}</li>
|
<li><strong>Game:</strong> {info.game}</li>
|
||||||
<li><strong>Location:</strong> {info.location}</li>
|
<li><strong>Location:</strong> {info.location}</li>
|
||||||
<li><strong>Notes:</strong> {info.notes}</li>
|
<li><strong>Notes:</strong> {info.notes}</li>
|
||||||
</ul>
|
</ul>
|
||||||
{:else}
|
|
||||||
{info}
|
|
||||||
{/if}
|
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -214,7 +175,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
|
<div class="bg-white text-black rounded-lg p-4 mb-2">
|
||||||
<p>
|
<p>
|
||||||
<strong>Where to catch: </strong>Currently missing - can you
|
<strong>Where to catch: </strong>Currently missing - can you
|
||||||
<a
|
<a
|
||||||
@@ -224,22 +185,39 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{#if pokedexEntry.notes}
|
|
||||||
<div class="bg-base-100 text-base-content rounded-lg p-4 mb-2">
|
|
||||||
<p><strong>Dex Notes:</strong> {pokedexEntry.notes}</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.dex-column {
|
.dex-column {
|
||||||
flex: 1;
|
width: 300px;
|
||||||
min-width: 250px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.sprite-container {
|
.sprite-container {
|
||||||
width: 100%;
|
width: 68px;
|
||||||
aspect-ratio: 1;
|
height: 68px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-checkbox {
|
||||||
|
appearance: none;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 2px solid #000;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 1.5rem;
|
||||||
|
display: inline-block;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-checkbox:checked {
|
||||||
|
background-color: #00bfff;
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-position: center center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-textarea {
|
||||||
|
min-height: 3rem;
|
||||||
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,212 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import type { Pokedex } from '$lib/models/Pokedex';
|
|
||||||
|
|
||||||
export let pokedex: Partial<Pokedex> = {
|
|
||||||
name: '',
|
|
||||||
description: '',
|
|
||||||
isLivingDex: false,
|
|
||||||
isShinyDex: false,
|
|
||||||
isOriginDex: false,
|
|
||||||
isFormDex: false,
|
|
||||||
gameScope: null,
|
|
||||||
dexScopes: []
|
|
||||||
};
|
|
||||||
export let mode: 'create' | 'edit' = 'create';
|
|
||||||
export let onSubmit: () => void;
|
|
||||||
export let onCancel: () => void;
|
|
||||||
|
|
||||||
type GameDex = {
|
|
||||||
id: string;
|
|
||||||
displayName: string;
|
|
||||||
sortOrder: number;
|
|
||||||
isDlc: boolean;
|
|
||||||
parentDexId: string | null;
|
|
||||||
};
|
|
||||||
type GameSummary = {
|
|
||||||
displayName: string;
|
|
||||||
releaseYear: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
let gameDexes: Record<string, GameDex[]> = {};
|
|
||||||
let gameOrder: string[] = [];
|
|
||||||
let gameList: GameSummary[] = [];
|
|
||||||
let availableDexes: GameDex[] = [];
|
|
||||||
let loadingDexes = true;
|
|
||||||
let lastGameScope: string | null = null;
|
|
||||||
let dexScopesInitialized = false;
|
|
||||||
let hasSeenGameScope = false;
|
|
||||||
|
|
||||||
// Fetch available game dexes from the database
|
|
||||||
onMount(async () => {
|
|
||||||
try {
|
|
||||||
const response = await fetch('/api/game-dexes');
|
|
||||||
if (response.ok) {
|
|
||||||
const data = await response.json();
|
|
||||||
gameDexes = data.gameDexes || {};
|
|
||||||
gameOrder = data.gameOrder || Object.keys(gameDexes);
|
|
||||||
gameList = data.games || [];
|
|
||||||
} else {
|
|
||||||
console.error('Failed to fetch game dexes');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error fetching game dexes:', error);
|
|
||||||
} finally {
|
|
||||||
loadingDexes = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Validation
|
|
||||||
$: hasAtLeastOneType =
|
|
||||||
pokedex.isLivingDex || pokedex.isShinyDex || pokedex.isOriginDex || pokedex.isFormDex;
|
|
||||||
$: hasDexScope =
|
|
||||||
!pokedex.gameScope || (pokedex.dexScopes && pokedex.dexScopes.length > 0);
|
|
||||||
$: canSubmit =
|
|
||||||
pokedex.name && pokedex.name.trim() !== '' && hasAtLeastOneType && hasDexScope;
|
|
||||||
|
|
||||||
$: if (pokedex.gameScope !== lastGameScope) {
|
|
||||||
const shouldResetDexes = mode === 'create' || hasSeenGameScope;
|
|
||||||
lastGameScope = pokedex.gameScope || null;
|
|
||||||
dexScopesInitialized = false;
|
|
||||||
if (shouldResetDexes) {
|
|
||||||
pokedex.dexScopes = [];
|
|
||||||
}
|
|
||||||
if (!pokedex.gameScope) {
|
|
||||||
availableDexes = [];
|
|
||||||
}
|
|
||||||
hasSeenGameScope = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$: if (!loadingDexes && pokedex.gameScope) {
|
|
||||||
availableDexes = gameDexes[pokedex.gameScope] || [];
|
|
||||||
if (!dexScopesInitialized) {
|
|
||||||
if (!pokedex.dexScopes || pokedex.dexScopes.length === 0) {
|
|
||||||
pokedex.dexScopes = availableDexes.map((dex) => dex.id);
|
|
||||||
}
|
|
||||||
dexScopesInitialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSubmit() {
|
|
||||||
if (canSubmit) {
|
|
||||||
onSubmit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="form-control w-full">
|
|
||||||
<label class="label" for="pokedex-name">
|
|
||||||
<span class="label-text">Name</span>
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
id="pokedex-name"
|
|
||||||
type="text"
|
|
||||||
placeholder="My Living Dex"
|
|
||||||
class="input input-bordered w-full"
|
|
||||||
bind:value={pokedex.name}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-control w-full">
|
|
||||||
<label class="label" for="pokedex-description">
|
|
||||||
<span class="label-text">Description (optional)</span>
|
|
||||||
</label>
|
|
||||||
<textarea
|
|
||||||
id="pokedex-description"
|
|
||||||
class="textarea textarea-bordered h-24"
|
|
||||||
placeholder="Describe your pokédex..."
|
|
||||||
bind:value={pokedex.description}
|
|
||||||
></textarea>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-control w-full">
|
|
||||||
<fieldset class="w-full">
|
|
||||||
<legend class="label">
|
|
||||||
<span class="label-text">Type(s)</span>
|
|
||||||
<span class="label-text-alt text-error"
|
|
||||||
>{!hasAtLeastOneType ? 'At least one type required' : ''}</span
|
|
||||||
>
|
|
||||||
</legend>
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
<label class="label cursor-pointer justify-start gap-3">
|
|
||||||
<input type="checkbox" class="checkbox" bind:checked={pokedex.isLivingDex} />
|
|
||||||
<span class="label-text">Living Dex (one of each Pokémon)</span>
|
|
||||||
</label>
|
|
||||||
<label class="label cursor-pointer justify-start gap-3">
|
|
||||||
<input type="checkbox" class="checkbox" bind:checked={pokedex.isShinyDex} />
|
|
||||||
<span class="label-text">Shiny Dex (shiny variants only)</span>
|
|
||||||
</label>
|
|
||||||
<label class="label cursor-pointer justify-start gap-3">
|
|
||||||
<input type="checkbox" class="checkbox" bind:checked={pokedex.isOriginDex} />
|
|
||||||
<span class="label-text">Origin Dex (caught in native regions)</span>
|
|
||||||
</label>
|
|
||||||
<label class="label cursor-pointer justify-start gap-3">
|
|
||||||
<input type="checkbox" class="checkbox" bind:checked={pokedex.isFormDex} />
|
|
||||||
<span class="label-text">Form Dex (all forms included)</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-control w-full">
|
|
||||||
<label class="label" for="game-scope">
|
|
||||||
<span class="label-text">Game Scope</span>
|
|
||||||
</label>
|
|
||||||
<select
|
|
||||||
id="game-scope"
|
|
||||||
class="select select-bordered"
|
|
||||||
bind:value={pokedex.gameScope}
|
|
||||||
disabled={loadingDexes}
|
|
||||||
>
|
|
||||||
<option value={null}>All Games</option>
|
|
||||||
{#if loadingDexes}
|
|
||||||
<option disabled>Loading games...</option>
|
|
||||||
{:else}
|
|
||||||
{#if gameList.length > 0}
|
|
||||||
{#each gameList as game}
|
|
||||||
<option value={game.displayName}>{game.displayName}</option>
|
|
||||||
{/each}
|
|
||||||
{:else}
|
|
||||||
{#each gameOrder.length > 0 ? gameOrder : Object.keys(gameDexes) as game}
|
|
||||||
<option value={game}>{game}</option>
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if pokedex.gameScope}
|
|
||||||
<div class="form-control w-full">
|
|
||||||
<fieldset class="w-full">
|
|
||||||
<legend class="label">
|
|
||||||
<span class="label-text">Dex Scope</span>
|
|
||||||
<span class="label-text-alt text-error">{!hasDexScope ? 'Select at least one dex' : ''}</span>
|
|
||||||
</legend>
|
|
||||||
{#if availableDexes.length === 0}
|
|
||||||
<p class="text-sm text-error">No dexes found for this game.</p>
|
|
||||||
{:else}
|
|
||||||
<div class="flex flex-col gap-2">
|
|
||||||
{#each availableDexes as dex}
|
|
||||||
<label class="label cursor-pointer justify-start gap-3">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox"
|
|
||||||
value={dex.id}
|
|
||||||
bind:group={pokedex.dexScopes}
|
|
||||||
/>
|
|
||||||
<span class="label-text">{dex.displayName}</span>
|
|
||||||
</label>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class="modal-action">
|
|
||||||
<button class="btn btn-ghost" type="button" on:click={onCancel}>Cancel</button>
|
|
||||||
<button class="btn btn-primary" type="button" on:click={handleSubmit} disabled={!canSubmit}>
|
|
||||||
{mode === 'create' ? 'Create' : 'Save'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
@@ -1,111 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { onMount, onDestroy } from 'svelte';
|
|
||||||
|
|
||||||
export let isOpen: boolean;
|
|
||||||
export let onClose: () => void;
|
|
||||||
|
|
||||||
function handleBackdropClick() {
|
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleKeyDown(event: KeyboardEvent) {
|
|
||||||
if (event.key === 'Escape' && isOpen) {
|
|
||||||
onClose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
window.addEventListener('keydown', handleKeyDown);
|
|
||||||
});
|
|
||||||
|
|
||||||
onDestroy(() => {
|
|
||||||
window.removeEventListener('keydown', handleKeyDown);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if isOpen}
|
|
||||||
<div class="modal modal-open" role="dialog" aria-modal="true">
|
|
||||||
<div class="modal-box-custom bg-primary text-primary-content">
|
|
||||||
<button class="close-button" on:click={onClose} aria-label="Close"> ✕ </button>
|
|
||||||
<div class="modal-content">
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="modal-backdrop bg-black/50"
|
|
||||||
aria-label="Close modal"
|
|
||||||
on:click={handleBackdropClick}
|
|
||||||
></button>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.modal-backdrop {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-box-custom {
|
|
||||||
max-width: 72rem;
|
|
||||||
width: 100%;
|
|
||||||
max-height: 90vh;
|
|
||||||
border: none;
|
|
||||||
box-shadow: 0 25px 50px -12px rgb(0 0 0 / 0.5);
|
|
||||||
outline: none;
|
|
||||||
position: relative;
|
|
||||||
border-radius: 1rem;
|
|
||||||
padding: 0.5rem;
|
|
||||||
overflow-y: auto;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-button {
|
|
||||||
position: absolute;
|
|
||||||
right: 1rem;
|
|
||||||
top: 1rem;
|
|
||||||
width: 2.5rem;
|
|
||||||
height: 2.5rem;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: rgba(0, 0, 0, 0.3);
|
|
||||||
color: white;
|
|
||||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: bold;
|
|
||||||
cursor: pointer;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
transition: all 0.2s;
|
|
||||||
z-index: 10;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-button:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
border-color: rgba(255, 255, 255, 0.5);
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remove margin and background from card inside modal */
|
|
||||||
.modal-content :global(.dex-entry) {
|
|
||||||
margin-bottom: 0;
|
|
||||||
background-color: transparent !important;
|
|
||||||
box-shadow: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.modal-box-custom {
|
|
||||||
width: 91.666667%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Pagination from '$lib/components/Pagination.svelte';
|
||||||
|
|
||||||
|
export let viewAsBoxes = false;
|
||||||
|
export let currentPage = 1;
|
||||||
|
export let itemsPerPage = 20;
|
||||||
|
export let totalPages = 0;
|
||||||
|
export let showForms = true;
|
||||||
|
export let showOrigins = true;
|
||||||
|
export let showShiny = false;
|
||||||
|
export let catchRegion = '';
|
||||||
|
export let catchGame = '';
|
||||||
|
export let toggleForms = () => {};
|
||||||
|
export let toggleOrigins = () => {};
|
||||||
|
export let toggleShiny = () => {};
|
||||||
|
export let getData = () => {};
|
||||||
|
export let toggleViewAsBoxes = () => {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<aside
|
||||||
|
class="menu bg-gray-800 text-white min-h-full w-64 p-4 lg:fixed xs:top-0 lg:left-0 h-full lg:h-5/6"
|
||||||
|
>
|
||||||
|
<h2 class="text-2xl font-semibold mb-4">Views</h2>
|
||||||
|
<ul>
|
||||||
|
<li class="mb-2">
|
||||||
|
<button class="block p-2 hover:bg-gray-700 rounded" on:click={toggleViewAsBoxes}>
|
||||||
|
{viewAsBoxes ? 'Switch to List View' : 'Switch to Box View'}
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h2 class="text-2xl font-semibold mb-4">Filters</h2>
|
||||||
|
<ul>
|
||||||
|
<li class="mb-2">
|
||||||
|
<button class="block p-2 hover:bg-gray-700 rounded" on:click={toggleForms}>
|
||||||
|
Toggle Forms (Currently {showForms ? 'On' : 'Off'})
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<button class="block p-2 hover:bg-gray-700 rounded" on:click={toggleOrigins}>
|
||||||
|
Toggle Origins (Currently {showOrigins ? 'On' : 'Off'})
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li class="mb-2">
|
||||||
|
<button class="block p-2 hover:bg-gray-700 rounded" on:click={toggleShiny}>
|
||||||
|
Toggle Shiny (Currently {showShiny ? 'On' : 'Off'})
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="catchRegionSelect">Region to catch in:</label>
|
||||||
|
<select
|
||||||
|
id="catchRegionSelect"
|
||||||
|
class="select select-bordered w-full max-w-xs text-black"
|
||||||
|
bind:value={catchRegion}
|
||||||
|
on:change={getData}
|
||||||
|
>
|
||||||
|
<option value="">All</option>
|
||||||
|
<option value="Kanto">Kanto (Red, Blue, Yellow, LG: Pikachu, LG: Eevee)</option>
|
||||||
|
<option value="Johto">Johto (Gold, Silver, Crystal, HG, SS)</option>
|
||||||
|
<option value="Hoenn">Hoenn (Ruby, Sapphire, Emerald, OR, AS)</option>
|
||||||
|
<option value="Sinnoh">Sinnoh (Diamond, Pearl, Platinum, BD, SP)</option>
|
||||||
|
<option value="Unova">Unova (Black, White, Black2, White2, Dream Radar)</option>
|
||||||
|
<option value="Kalos">Kalos (X, Y)</option>
|
||||||
|
<option value="Alola">Alola (Sun, Moon, Moon Demo, US, UM)</option>
|
||||||
|
<option value="Galar">Galar (Sword, Shield)</option>
|
||||||
|
<option value="Hisui">Hisui (PLA)</option>
|
||||||
|
<option value="Paldea">Paldea (Scarlet, Violet)</option>
|
||||||
|
<option value="Unknown">Unknown (Home, Go)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="catchGameSelect">Game to catch in: {catchGame}</label>
|
||||||
|
<select
|
||||||
|
id="catchGameSelect"
|
||||||
|
class="select select-bordered w-full max-w-xs text-black"
|
||||||
|
bind:value={catchGame}
|
||||||
|
on:change={getData}
|
||||||
|
>
|
||||||
|
<option value="">All</option>
|
||||||
|
<option value="Red">Red (Kanto)</option>
|
||||||
|
<option value="Blue">Blue (Kanto)</option>
|
||||||
|
<option value="Yellow">Yellow (Kanto)</option>
|
||||||
|
<option value="LG: Pikachu">LG: Pikachu (Kanto)</option>
|
||||||
|
<option value="LG: Eevee">LG: Eevee (Kanto)</option>
|
||||||
|
<option value="Gold">Gold (Johto)</option>
|
||||||
|
<option value="Silver">Silver (Johto)</option>
|
||||||
|
<option value="Crystal">Crystal (Johto)</option>
|
||||||
|
<option value="HG">HG (Johto)</option>
|
||||||
|
<option value="SS">SS (Johto)</option>
|
||||||
|
<option value="Ruby">Ruby (Hoenn)</option>
|
||||||
|
<option value="Sapphire">Sapphire (Hoenn)</option>
|
||||||
|
<option value="Emerald">Emerald (Hoenn)</option>
|
||||||
|
<option value="OR">OR (Hoenn)</option>
|
||||||
|
<option value="AS">AS (Hoenn)</option>
|
||||||
|
<option value="Diamond">Diamond (Sinnoh)</option>
|
||||||
|
<option value="Pearl">Pearl (Sinnoh)</option>
|
||||||
|
<option value="Platinum">Platinum (Sinnoh)</option>
|
||||||
|
<option value="BD">BD (Sinnoh)</option>
|
||||||
|
<option value="SP">SP (Sinnoh)</option>
|
||||||
|
<option value="Black">Black (Unova)</option>
|
||||||
|
<option value="White">White (Unova)</option>
|
||||||
|
<option value="Black2">Black2 (Unova)</option>
|
||||||
|
<option value="White2">White2 (Unova)</option>
|
||||||
|
<option value="Dream Radar">Dream Radar (Unova)</option>
|
||||||
|
<option value="X">X (Kalos)</option>
|
||||||
|
<option value="Y">Y (Kalos)</option>
|
||||||
|
<option value="Sun">Sun (Alola)</option>
|
||||||
|
<option value="Moon">Moon (Alola)</option>
|
||||||
|
<option value="Moon Demo">Moon Demo (Alola)</option>
|
||||||
|
<option value="US">US (Alola)</option>
|
||||||
|
<option value="UM">UM (Alola)</option>
|
||||||
|
<option value="Sword">Sword (Galar)</option>
|
||||||
|
<option value="Shield">Shield (Galar)</option>
|
||||||
|
<option value="PLA">PLA (Hisui)</option>
|
||||||
|
<option value="Scarlet">Scarlet (Paldea)</option>
|
||||||
|
<option value="Violet">Violet (Paldea)</option>
|
||||||
|
<option value="Home">Home (Unknown)</option>
|
||||||
|
<option value="Go">Go (Unknown)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if !viewAsBoxes}
|
||||||
|
<h2 class="text-2xl font-semibold mb-4">Paging</h2>
|
||||||
|
<div>
|
||||||
|
<Pagination bind:currentPage bind:itemsPerPage bind:totalPages />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</aside>
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import type { CatchRecord } from '$lib/models/CatchRecord';
|
import type { CatchRecord } from '$lib/models/CatchRecord';
|
||||||
import type { CombinedData } from '$lib/models/CombinedData';
|
import type { CombinedData } from '$lib/models/CombinedData';
|
||||||
import { calculateBoxPlacement } from '$lib/utils/boxPlacement';
|
import type { PokedexEntry } from '$lib/models/PokedexEntry';
|
||||||
import PokemonSprite from '$lib/components/PokemonSprite.svelte';
|
import PokemonSprite from '$lib/components/PokemonSprite.svelte';
|
||||||
import Tooltip from '$lib/components/Tooltip.svelte';
|
import Tooltip from '$lib/components/Tooltip.svelte';
|
||||||
|
|
||||||
export let showShiny = false;
|
export let showShiny = false;
|
||||||
export let combinedData: CombinedData[] | null;
|
export let combinedData: CombinedData[] | null;
|
||||||
export let boxNumbers: number[] = [];
|
export let boxNumbers = Array<number>;
|
||||||
|
export let currentPlacement = 'boxPlacementForms';
|
||||||
export let creatingRecords = false;
|
export let creatingRecords = false;
|
||||||
export let totalRecordsCreated = 0;
|
export let totalRecordsCreated = 0;
|
||||||
export let failedToLoad = false;
|
export let failedToLoad = false;
|
||||||
@@ -18,522 +18,77 @@
|
|||||||
export let markBoxAsInHome = (boxNumber: number) => {};
|
export let markBoxAsInHome = (boxNumber: number) => {};
|
||||||
export let markBoxAsNotInHome = (boxNumber: number) => {};
|
export let markBoxAsNotInHome = (boxNumber: number) => {};
|
||||||
export let createCatchRecords = () => {};
|
export let createCatchRecords = () => {};
|
||||||
export let onPokemonClick: (pokemon: CombinedData) => void = () => {};
|
|
||||||
|
|
||||||
let filterNotCaught = false;
|
function cellBackgroundColourClass(catchRecord: CatchRecord) {
|
||||||
let filterNeedsToEvolve = false;
|
if (catchRecord.caught) {
|
||||||
let filterInHome = false;
|
return 'bg-green-100/50';
|
||||||
let filterNotInHome = false;
|
} else if (catchRecord.haveToEvolve) {
|
||||||
|
return 'bg-yellow-100/50';
|
||||||
// Bulk actions menu state (one open menu at a time)
|
} else {
|
||||||
let openBulkMenuForBox: number | null = null;
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
const close = () => {
|
|
||||||
openBulkMenuForBox = null;
|
|
||||||
};
|
|
||||||
window.addEventListener('click', close);
|
|
||||||
return () => window.removeEventListener('click', close);
|
|
||||||
});
|
|
||||||
|
|
||||||
let filteredCombinedData: CombinedData[] = [];
|
|
||||||
let filteredTotal = 0;
|
|
||||||
let overallTotal = 0;
|
|
||||||
let overallCaughtCount = 0;
|
|
||||||
let overallNotCaughtCount = 0;
|
|
||||||
let overallNeedsToEvolveCount = 0;
|
|
||||||
let overallInHomeCount = 0;
|
|
||||||
let overallNotInHomeCount = 0;
|
|
||||||
let filtersActive = false;
|
|
||||||
let filtersKey = '';
|
|
||||||
|
|
||||||
function normalizedStatus(catchRecord: CatchRecord | null) {
|
|
||||||
return {
|
|
||||||
caught: !!catchRecord?.caught,
|
|
||||||
needsToEvolve: !!catchRecord?.haveToEvolve,
|
|
||||||
inHome: !!catchRecord?.inHome
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function matchesFilters(catchRecord: CatchRecord | null) {
|
|
||||||
const status = normalizedStatus(catchRecord);
|
|
||||||
if (!filtersActive) return true;
|
|
||||||
|
|
||||||
const isCaught = status.caught || status.needsToEvolve;
|
|
||||||
const isNotCaught = !isCaught;
|
|
||||||
const isNeedsToEvolve = status.needsToEvolve;
|
|
||||||
const isInHome = status.inHome;
|
|
||||||
const isNotInHome = !status.inHome;
|
|
||||||
|
|
||||||
// OR within each group, AND between groups.
|
|
||||||
const progressGroupActive = filterNotCaught || filterNeedsToEvolve;
|
|
||||||
const homeGroupActive = filterInHome || filterNotInHome;
|
|
||||||
|
|
||||||
const progressMatch =
|
|
||||||
!progressGroupActive ||
|
|
||||||
(filterNotCaught && isNotCaught) ||
|
|
||||||
(filterNeedsToEvolve && isNeedsToEvolve);
|
|
||||||
|
|
||||||
const homeMatch =
|
|
||||||
!homeGroupActive || (filterInHome && isInHome) || (filterNotInHome && isNotInHome);
|
|
||||||
|
|
||||||
return progressMatch && homeMatch;
|
|
||||||
}
|
|
||||||
|
|
||||||
$: filtersActive = filterNotCaught || filterNeedsToEvolve || filterInHome || filterNotInHome;
|
|
||||||
$: filtersKey = `${filterNotCaught}-${filterNeedsToEvolve}-${filterInHome}-${filterNotInHome}`;
|
|
||||||
|
|
||||||
$: {
|
|
||||||
// Ensure this recalculates when any filter changes (Svelte doesn't track function internals).
|
|
||||||
filtersKey;
|
|
||||||
filteredCombinedData = combinedData
|
|
||||||
? combinedData.filter(({ catchRecord }) => matchesFilters(catchRecord))
|
|
||||||
: [];
|
|
||||||
}
|
|
||||||
|
|
||||||
$: filteredTotal = filteredCombinedData.length;
|
|
||||||
$: overallTotal = combinedData?.length ?? 0;
|
|
||||||
|
|
||||||
$: overallCaughtCount = (combinedData ?? []).reduce((acc, { catchRecord }) => {
|
|
||||||
const status = normalizedStatus(catchRecord);
|
|
||||||
// Treat "needs to evolve" as a subset of "caught" (it is caught, just not finished).
|
|
||||||
return acc + (status.caught || status.needsToEvolve ? 1 : 0);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
$: overallNotCaughtCount = overallTotal - overallCaughtCount;
|
|
||||||
|
|
||||||
$: overallNeedsToEvolveCount = (combinedData ?? []).reduce((acc, { catchRecord }) => {
|
|
||||||
return acc + (normalizedStatus(catchRecord).needsToEvolve ? 1 : 0);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
$: overallInHomeCount = (combinedData ?? []).reduce((acc, { catchRecord }) => {
|
|
||||||
return acc + (normalizedStatus(catchRecord).inHome ? 1 : 0);
|
|
||||||
}, 0);
|
|
||||||
|
|
||||||
$: overallNotInHomeCount = overallTotal - overallInHomeCount;
|
|
||||||
|
|
||||||
const BOX_VIEW_LAYOUT_STORAGE_KEY = 'livingdex:boxViewLayout:v1';
|
|
||||||
type BoxViewLayout = 'comfortable' | 'compact' | 'ultra';
|
|
||||||
let boxViewLayout: BoxViewLayout = 'comfortable';
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
try {
|
|
||||||
const stored = localStorage.getItem(BOX_VIEW_LAYOUT_STORAGE_KEY);
|
|
||||||
if (stored === 'comfortable' || stored === 'compact' || stored === 'ultra') {
|
|
||||||
boxViewLayout = stored;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// ignore (privacy mode / disabled storage)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function persistBoxViewLayout(next: BoxViewLayout) {
|
|
||||||
boxViewLayout = next;
|
|
||||||
try {
|
|
||||||
localStorage.setItem(BOX_VIEW_LAYOUT_STORAGE_KEY, next);
|
|
||||||
} catch {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onBoxViewLayoutChange(event: Event) {
|
|
||||||
const next = (event.currentTarget as HTMLSelectElement).value;
|
|
||||||
if (next === 'comfortable' || next === 'compact' || next === 'ultra') {
|
|
||||||
persistBoxViewLayout(next);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$: boxesPerRow = boxViewLayout === 'comfortable' ? 2 : boxViewLayout === 'compact' ? 3 : 4;
|
|
||||||
$: cellPaddingRem =
|
|
||||||
boxViewLayout === 'comfortable' ? 1 : boxViewLayout === 'compact' ? 0.6 : 0.45;
|
|
||||||
$: spriteSizePx = boxViewLayout === 'comfortable' ? 64 : boxViewLayout === 'compact' ? 52 : 44;
|
|
||||||
|
|
||||||
function cellStatusClasses(catchRecord: CatchRecord | null) {
|
|
||||||
// Keep borders/layout unchanged; rely on clearer fills + badges instead.
|
|
||||||
if (catchRecord?.caught) {
|
|
||||||
// Match legend (green-600) while keeping sprites readable.
|
|
||||||
return 'bg-green-600/15';
|
|
||||||
}
|
|
||||||
if (catchRecord?.haveToEvolve) {
|
|
||||||
// Match legend (yellow-500) while keeping sprites readable.
|
|
||||||
return 'bg-yellow-500/20';
|
|
||||||
}
|
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function statusLabel(catchRecord: CatchRecord | null) {
|
|
||||||
const parts: string[] = [];
|
|
||||||
if (catchRecord?.caught) parts.push('Caught');
|
|
||||||
if (catchRecord?.haveToEvolve) parts.push('Needs to evolve');
|
|
||||||
if (catchRecord?.inHome) parts.push('In HOME');
|
|
||||||
return parts.length ? parts.join(', ') : 'Not caught';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function cellBackgroundColourStyle(index: number, catchRecord: CatchRecord | null) {
|
function cellBackgroundColourStyle(pokedexEntry: PokedexEntry, catchRecord: CatchRecord) {
|
||||||
if (catchRecord?.caught || catchRecord?.haveToEvolve) {
|
if (catchRecord.caught || catchRecord.haveToEvolve) {
|
||||||
return '';
|
return '';
|
||||||
} else {
|
} else {
|
||||||
const placement = calculateBoxPlacement(index);
|
if (pokedexEntry[currentPlacement].column % 2 === 0) {
|
||||||
if (placement.column % 2 === 0) {
|
return 'background-color: #ffffff';
|
||||||
return 'background-color: var(--ld-box-bg-even);';
|
|
||||||
} else {
|
} else {
|
||||||
return 'background-color: var(--ld-box-bg-odd);';
|
return 'background-color: #f9f9f9;';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function onInHomeFilterChange(event: Event) {
|
|
||||||
const checked = (event.currentTarget as HTMLInputElement).checked;
|
|
||||||
if (checked) filterNotInHome = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function onNotInHomeFilterChange(event: Event) {
|
|
||||||
const checked = (event.currentTarget as HTMLInputElement).checked;
|
|
||||||
if (checked) filterInHome = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const POKEMON_PER_BOX = 30;
|
|
||||||
const BOX_POSITIONS = Array.from({ length: POKEMON_PER_BOX }, (_, i) => i);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<main class="flex-1 p-4 w-full">
|
<main class="flex-1 p-4 w-full">
|
||||||
<div class="max-w-fit mx-auto">
|
<div class="max-w-fit mx-auto">
|
||||||
{#if combinedData && combinedData.length > 0}
|
{#if combinedData && combinedData.length > 0}
|
||||||
<div class="container mx-auto">
|
<div class="container mx-auto">
|
||||||
<div class="card bg-base-100 shadow mb-4">
|
<div class="flex flex-wrap -mx-2">
|
||||||
<div class="card-body p-4 flex flex-col gap-3">
|
|
||||||
<div class="flex flex-wrap items-center gap-3">
|
|
||||||
<label class="label p-0" for="box-view-layout">
|
|
||||||
<span class="label-text font-semibold">Box view layout</span>
|
|
||||||
</label>
|
|
||||||
<select
|
|
||||||
id="box-view-layout"
|
|
||||||
class="select select-bordered select-sm"
|
|
||||||
bind:value={boxViewLayout}
|
|
||||||
on:change={onBoxViewLayoutChange}
|
|
||||||
aria-label="Choose box view layout density"
|
|
||||||
>
|
|
||||||
<option value="comfortable">Comfortable (2 boxes/row)</option>
|
|
||||||
<option value="compact">Compact (3 boxes/row)</option>
|
|
||||||
<option value="ultra">Ultra (4 boxes/row)</option>
|
|
||||||
</select>
|
|
||||||
|
|
||||||
<div class="flex flex-wrap items-center gap-2 text-sm">
|
|
||||||
<span class="font-semibold">Legend:</span>
|
|
||||||
<span
|
|
||||||
class="inline-flex items-center gap-1 rounded-full border border-green-700 bg-green-600 px-2 py-0.5 text-white"
|
|
||||||
>
|
|
||||||
<span class="status-badge status-badge--caught" aria-hidden="true">
|
|
||||||
<svg
|
|
||||||
class="status-icon"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="#ffffff"
|
|
||||||
stroke-width="3"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path d="M5 13l4 4L19 7" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span>Caught</span>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="inline-flex items-center gap-1 rounded-full border border-yellow-700 bg-yellow-500 px-2 py-0.5 text-white"
|
|
||||||
>
|
|
||||||
<span class="status-badge status-badge--evolve" aria-hidden="true">
|
|
||||||
<svg
|
|
||||||
class="status-icon"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="#ffffff"
|
|
||||||
stroke-width="3"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path d="M12 19V5" />
|
|
||||||
<path d="M5 12l7-7 7 7" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span>Caught but needs to evolve</span>
|
|
||||||
</span>
|
|
||||||
<span
|
|
||||||
class="inline-flex items-center gap-1 rounded-full border border-sky-700 bg-sky-600 px-2 py-0.5 text-white"
|
|
||||||
>
|
|
||||||
<span class="status-badge status-badge--home" aria-hidden="true">
|
|
||||||
<svg
|
|
||||||
class="status-icon"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="#ffffff"
|
|
||||||
stroke="#ffffff"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
>
|
|
||||||
<path d="M12 3 3 10.5V21a1 1 0 0 0 1 1h5v-6h6v6h5a1 1 0 0 0 1-1V10.5L12 3Z" />
|
|
||||||
</svg>
|
|
||||||
</span>
|
|
||||||
<span>In Home</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex flex-col gap-3">
|
|
||||||
<div class="flex flex-wrap items-center gap-4">
|
|
||||||
<span class="font-semibold">Filters:</span>
|
|
||||||
<label class="label cursor-pointer gap-2 p-0">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox checkbox-sm"
|
|
||||||
bind:checked={filterNotCaught}
|
|
||||||
/>
|
|
||||||
<span class="label-text">Not caught</span>
|
|
||||||
</label>
|
|
||||||
<label class="label cursor-pointer gap-2 p-0">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox checkbox-sm"
|
|
||||||
bind:checked={filterNeedsToEvolve}
|
|
||||||
/>
|
|
||||||
<span class="label-text">Needs to evolve</span>
|
|
||||||
</label>
|
|
||||||
<label class="label cursor-pointer gap-2 p-0">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox checkbox-sm"
|
|
||||||
bind:checked={filterInHome}
|
|
||||||
on:change={onInHomeFilterChange}
|
|
||||||
/>
|
|
||||||
<span class="label-text">In HOME</span>
|
|
||||||
</label>
|
|
||||||
<label class="label cursor-pointer gap-2 p-0">
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
class="checkbox checkbox-sm"
|
|
||||||
bind:checked={filterNotInHome}
|
|
||||||
on:change={onNotInHomeFilterChange}
|
|
||||||
/>
|
|
||||||
<span class="label-text">Not in HOME</span>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="flex flex-wrap items-center justify-between gap-2 rounded-box bg-base-200/60 px-3 py-2"
|
|
||||||
>
|
|
||||||
<div class="text-sm text-base-content/70">
|
|
||||||
<span class="font-semibold text-base-content">Caught</span>
|
|
||||||
{overallCaughtCount}
|
|
||||||
<span class="mx-2">•</span>
|
|
||||||
<span class="font-semibold text-base-content">Not caught</span>
|
|
||||||
{overallNotCaughtCount}
|
|
||||||
<span class="mx-2">•</span>
|
|
||||||
<span class="font-semibold text-base-content">Needs to evolve</span>
|
|
||||||
{overallNeedsToEvolveCount}
|
|
||||||
<span class="mx-2">•</span>
|
|
||||||
<span class="font-semibold text-base-content">In HOME</span>
|
|
||||||
{overallInHomeCount}
|
|
||||||
<span class="mx-2">•</span>
|
|
||||||
<span class="font-semibold text-base-content">Not in HOME</span>
|
|
||||||
{overallNotInHomeCount}
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-outline">
|
|
||||||
Showing {filteredTotal} of {overallTotal}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
class="boxes-grid"
|
|
||||||
style="--boxes-per-row: {boxesPerRow}; --cell-padding: {cellPaddingRem}rem; --sprite-size: {spriteSizePx}px;"
|
|
||||||
>
|
|
||||||
{#each boxNumbers as boxNumber}
|
{#each boxNumbers as boxNumber}
|
||||||
{@const bulkMenuId = `box-${boxNumber}-bulk-menu`}
|
<div class="mb-8 md:w-1/2 px-2">
|
||||||
<div class="mb-8">
|
<h2 class="text-xl font-bold mb-4">Box {boxNumber}</h2>
|
||||||
<div class="flex flex-wrap items-center justify-between gap-3 mb-4 relative z-20">
|
<button class="btn" on:click={markBoxAsNotCaught(boxNumber)}>
|
||||||
<h2 class="text-xl font-bold">Box {boxNumber}</h2>
|
Mark box as not 'caught'
|
||||||
<div class="relative">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="btn btn-sm btn-outline relative z-[210]"
|
|
||||||
aria-label="Open bulk actions menu"
|
|
||||||
aria-haspopup="menu"
|
|
||||||
aria-controls={bulkMenuId}
|
|
||||||
aria-expanded={openBulkMenuForBox === boxNumber}
|
|
||||||
on:click={(event) => {
|
|
||||||
event.stopPropagation();
|
|
||||||
openBulkMenuForBox = openBulkMenuForBox === boxNumber ? null : boxNumber;
|
|
||||||
}}
|
|
||||||
on:keydown={(event) => {
|
|
||||||
if (event.key === 'Escape') openBulkMenuForBox = null;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
⋯
|
|
||||||
</button>
|
</button>
|
||||||
|
<button class="btn" on:click={markBoxAsCaught(boxNumber)}>
|
||||||
{#if openBulkMenuForBox === boxNumber}
|
Mark box as 'caught'
|
||||||
<ul
|
|
||||||
id={bulkMenuId}
|
|
||||||
class="menu bg-base-100 rounded-box absolute right-0 mt-2 z-[220] w-56 p-2 shadow border border-base-300"
|
|
||||||
>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click|stopPropagation={() => {
|
|
||||||
markBoxAsNotCaught(boxNumber);
|
|
||||||
openBulkMenuForBox = null;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Mark box as Not caught
|
|
||||||
</button>
|
</button>
|
||||||
</li>
|
<button class="btn" on:click={markBoxAsNeedsToEvolve(boxNumber)}
|
||||||
<li>
|
>Mark box as 'needs to evolve'</button
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click|stopPropagation={() => {
|
|
||||||
markBoxAsCaught(boxNumber);
|
|
||||||
openBulkMenuForBox = null;
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Mark box as Caught
|
<button class="btn" on:click={markBoxAsInHome(boxNumber)}
|
||||||
</button>
|
>Mark box as 'in Home'</button
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click|stopPropagation={() => {
|
|
||||||
markBoxAsNeedsToEvolve(boxNumber);
|
|
||||||
openBulkMenuForBox = null;
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Mark box as Needs to evolve
|
<button class="btn" on:click={markBoxAsNotInHome(boxNumber)}
|
||||||
</button>
|
>Mark box as not 'in Home'</button
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click|stopPropagation={() => {
|
|
||||||
markBoxAsInHome(boxNumber);
|
|
||||||
openBulkMenuForBox = null;
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Mark box as In HOME
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
on:click|stopPropagation={() => {
|
|
||||||
markBoxAsNotInHome(boxNumber);
|
|
||||||
openBulkMenuForBox = null;
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Mark box as Not in HOME
|
|
||||||
</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-6">
|
<div class="grid grid-cols-6">
|
||||||
{#each BOX_POSITIONS as positionInBox}
|
{#each combinedData as { pokedexEntry, catchRecord }}
|
||||||
{@const globalIndex = (boxNumber - 1) * POKEMON_PER_BOX + positionInBox}
|
{#if pokedexEntry[currentPlacement].box === boxNumber}
|
||||||
{@const placement = calculateBoxPlacement(globalIndex)}
|
<div
|
||||||
{@const entry = combinedData?.[globalIndex]}
|
class="pokemon-box {cellBackgroundColourClass(catchRecord)}"
|
||||||
{@const pokedexEntry = entry?.pokedexEntry}
|
style="grid-column-start: {pokedexEntry[currentPlacement]
|
||||||
{@const catchRecord = entry?.catchRecord ?? null}
|
.column}; grid-row-start: {pokedexEntry[currentPlacement].row};
|
||||||
{@const isFilteredOut =
|
{cellBackgroundColourStyle(pokedexEntry, catchRecord)}"
|
||||||
!!entry && filtersActive && !!filtersKey && !matchesFilters(catchRecord)}
|
|
||||||
{#if entry && pokedexEntry}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="pokemon-box {cellStatusClasses(catchRecord)} {isFilteredOut
|
|
||||||
? 'pokemon-box--filtered-out'
|
|
||||||
: 'hover:scale-105 hover:shadow-lg hover:z-50'} transition-all cursor-pointer relative"
|
|
||||||
style="grid-column-start: {placement.column}; grid-row-start: {placement.row};
|
|
||||||
{cellBackgroundColourStyle(globalIndex, catchRecord)}"
|
|
||||||
aria-disabled={isFilteredOut}
|
|
||||||
on:click={() => {
|
|
||||||
if (!isFilteredOut) onPokemonClick({ pokedexEntry, catchRecord });
|
|
||||||
}}
|
|
||||||
aria-label="View details for {pokedexEntry.pokemon}. Status: {statusLabel(
|
|
||||||
catchRecord
|
|
||||||
)}"
|
|
||||||
>
|
>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<div slot="hover-target" class="w-full h-full">
|
<div slot="hover-target">
|
||||||
{#if catchRecord?.caught}
|
{#if catchRecord.inHome}
|
||||||
<span
|
<span
|
||||||
class="status-badge status-badge--caught absolute left-0.5 status-badge-top z-10"
|
class="absolute -top-5 -right-4 z-2 p-1 text-secondary text-lg font-extrabold"
|
||||||
title="Caught"
|
>✓</span
|
||||||
>
|
>
|
||||||
<svg
|
|
||||||
class="status-icon"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="3"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path d="M5 13l4 4L19 7" />
|
|
||||||
</svg>
|
|
||||||
<span class="sr-only">Caught</span>
|
|
||||||
</span>
|
|
||||||
{:else if catchRecord?.haveToEvolve}
|
|
||||||
<span
|
|
||||||
class="status-badge status-badge--evolve absolute left-0.5 status-badge-top z-10"
|
|
||||||
title="Caught but needs to evolve"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
class="status-icon"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="3"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path d="M12 19V5" />
|
|
||||||
<path d="M5 12l7-7 7 7" />
|
|
||||||
</svg>
|
|
||||||
<span class="sr-only">Caught but needs to evolve</span>
|
|
||||||
</span>
|
|
||||||
{/if}
|
{/if}
|
||||||
{#if catchRecord?.inHome}
|
|
||||||
<span
|
|
||||||
class="status-badge status-badge--home absolute right-0.5 status-badge-top z-10"
|
|
||||||
title="In Pokémon HOME"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
class="status-icon"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="currentColor"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 3 3 10.5V21a1 1 0 0 0 1 1h5v-6h6v6h5a1 1 0 0 0 1-1V10.5L12 3Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
<span class="sr-only">In HOME</span>
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
<div class="pokemon-box-inner">
|
|
||||||
<PokemonSprite
|
<PokemonSprite
|
||||||
pokemonName={pokedexEntry.pokemon}
|
pokemonName={pokedexEntry.pokemon}
|
||||||
pokedexNumber={pokedexEntry.pokedexNumber}
|
pokedexNumber={pokedexEntry.pokedexNumber}
|
||||||
form={pokedexEntry.form}
|
form={pokedexEntry.form}
|
||||||
spriteKey={pokedexEntry.spriteKey}
|
|
||||||
shiny={showShiny}
|
shiny={showShiny}
|
||||||
/>
|
/>
|
||||||
</div>
|
<span class="md:hidden">ⓘ</span>
|
||||||
</div>
|
</div>
|
||||||
<div slot="tooltip">
|
<div slot="tooltip">
|
||||||
<div class="font-bold">
|
<div class="font-bold">
|
||||||
@@ -542,27 +97,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>{pokedexEntry.pokedexNumber.toString().padStart(3, '0')}</div>
|
<div>{pokedexEntry.pokedexNumber.toString().padStart(3, '0')}</div>
|
||||||
<div>
|
<div>
|
||||||
Caught: {catchRecord?.caught ? 'Yes' : 'No'} <br />
|
Caught: {catchRecord.caught ? 'Yes' : 'No'} <br />
|
||||||
Caught but needs to Evolve: {catchRecord?.haveToEvolve ? 'Yes' : 'No'}
|
Needs to Evolve: {catchRecord.haveToEvolve ? 'Yes' : 'No'} <br />
|
||||||
<br />
|
In Home: {catchRecord.inHome ? 'Yes' : 'No'}
|
||||||
In Home: {catchRecord?.inHome ? 'Yes' : 'No'}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</button>
|
|
||||||
{:else}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="pokemon-box pokemon-box--empty"
|
|
||||||
disabled
|
|
||||||
style="grid-column-start: {placement.column}; grid-row-start: {placement.row};
|
|
||||||
{cellBackgroundColourStyle(globalIndex, null)}"
|
|
||||||
aria-label="Empty box slot"
|
|
||||||
>
|
|
||||||
<div class="pokemon-box-inner" aria-hidden="true">
|
|
||||||
<span class="sprite-placeholder" />
|
|
||||||
</div>
|
</div>
|
||||||
</button>
|
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
@@ -595,150 +136,8 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/*
|
|
||||||
Theme-aware backgrounds for non-caught box slots.
|
|
||||||
- Light mode (`pokeball`) keeps the original exact colors.
|
|
||||||
- Dark mode maps to DaisyUI theme base tokens so it stays consistent with the active theme.
|
|
||||||
*/
|
|
||||||
:global(:root) {
|
|
||||||
--ld-box-bg-even: var(--fallback-b1, oklch(var(--b1) / 1));
|
|
||||||
--ld-box-bg-odd: var(--fallback-b3, oklch(var(--b3) / 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
:global([data-theme='pokeball']) {
|
|
||||||
--ld-box-bg-even: #ffffff;
|
|
||||||
--ld-box-bg-odd: #f9f9f9;
|
|
||||||
}
|
|
||||||
|
|
||||||
.boxes-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(1, minmax(0, 1fr));
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
.boxes-grid {
|
|
||||||
grid-template-columns: repeat(var(--boxes-per-row), minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pokemon-box {
|
.pokemon-box {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
padding: 0;
|
padding: 1rem;
|
||||||
border-radius: 0;
|
|
||||||
/*
|
|
||||||
On small screens the grid columns get narrow; without an explicit ratio,
|
|
||||||
the button height becomes content-driven (padding + sprite) and you end up
|
|
||||||
with rectangular cells. Force each slot to be square.
|
|
||||||
*/
|
|
||||||
aspect-ratio: 1 / 1;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pokemon-box--filtered-out {
|
|
||||||
opacity: 0.25;
|
|
||||||
filter: grayscale(1);
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pokemon-box--empty {
|
|
||||||
opacity: 0.55;
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pokemon-box-inner {
|
|
||||||
padding: var(--cell-padding, 1rem);
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pokemon-box :global(img) {
|
|
||||||
width: var(--sprite-size, 64px);
|
|
||||||
height: var(--sprite-size, 64px);
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
display: block;
|
|
||||||
object-fit: contain;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sprite-placeholder {
|
|
||||||
width: var(--sprite-size, 64px);
|
|
||||||
height: var(--sprite-size, 64px);
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Mobile: keep 6 columns but prevent sprite/padding from forcing tall cells */
|
|
||||||
@media (max-width: 767px) {
|
|
||||||
.pokemon-box-inner {
|
|
||||||
/* cap padding so the sprite can fit inside small squares */
|
|
||||||
padding: min(var(--cell-padding, 1rem), 0.35rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pokemon-box :global(img) {
|
|
||||||
/* allow the sprite to shrink with the square cell */
|
|
||||||
width: min(var(--sprite-size, 64px), 100%);
|
|
||||||
height: min(var(--sprite-size, 64px), 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sprite-placeholder {
|
|
||||||
width: min(var(--sprite-size, 64px), 100%);
|
|
||||||
height: min(var(--sprite-size, 64px), 100%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge {
|
|
||||||
width: 0.95rem;
|
|
||||||
height: 0.95rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge-top {
|
|
||||||
top: 0.35rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-icon {
|
|
||||||
width: 0.85rem;
|
|
||||||
height: 0.85rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 1.15rem;
|
|
||||||
height: 1.15rem;
|
|
||||||
border-radius: 0.35rem;
|
|
||||||
font-weight: 900;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
line-height: 1;
|
|
||||||
border: none;
|
|
||||||
background: transparent;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge-top {
|
|
||||||
top: 0.7rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-icon {
|
|
||||||
width: 1rem;
|
|
||||||
height: 1rem;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge--caught {
|
|
||||||
color: #16a34a; /* green-600 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge--evolve {
|
|
||||||
color: #eab308; /* yellow-500 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.status-badge--home {
|
|
||||||
color: #0284c7; /* sky-600 */
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import PokedexEntryCatchRecord from './PokedexEntryCatchRecord.svelte';
|
||||||
|
import type { CombinedData } from '$lib/models/CombinedData';
|
||||||
|
|
||||||
|
export let showOrigins = true;
|
||||||
|
export let showForms = true;
|
||||||
|
export let showShiny = false;
|
||||||
|
export let combinedData: CombinedData[] | null;
|
||||||
|
export let creatingRecords = false;
|
||||||
|
export let totalRecordsCreated = 0;
|
||||||
|
export let failedToLoad = false;
|
||||||
|
export let updateACatch = (event: any) => {};
|
||||||
|
export let createCatchRecords = () => {};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<main class="flex-1 p-4 w-full">
|
||||||
|
<div class="max-w-min mx-auto">
|
||||||
|
{#if combinedData && combinedData.length > 0}
|
||||||
|
{#each combinedData as { pokedexEntry, catchRecord }}
|
||||||
|
<PokedexEntryCatchRecord
|
||||||
|
{pokedexEntry}
|
||||||
|
{showOrigins}
|
||||||
|
{showForms}
|
||||||
|
{showShiny}
|
||||||
|
bind:catchRecord
|
||||||
|
on:updateCatch={updateACatch}
|
||||||
|
/>
|
||||||
|
{/each}
|
||||||
|
{:else if failedToLoad}
|
||||||
|
{#if creatingRecords && totalRecordsCreated > 0}
|
||||||
|
<p>Processed {totalRecordsCreated} Pokédex entries so far...</p>
|
||||||
|
<p>Please be patient, this may take some time.</p>
|
||||||
|
{:else if creatingRecords}
|
||||||
|
<p>Processing...</p>
|
||||||
|
<p>Please be patient, this may take some time.</p>
|
||||||
|
{:else}
|
||||||
|
<h1>Failed to load</h1>
|
||||||
|
<p>
|
||||||
|
If you're seeing this, you probably haven't created your Pokédex data yet. Please do so by
|
||||||
|
clicking this button.
|
||||||
|
</p>
|
||||||
|
<button class="btn" on:click={createCatchRecords}>Create Pokédex data</button>
|
||||||
|
{/if}
|
||||||
|
{:else}
|
||||||
|
<div class="min-w-max mx-auto">
|
||||||
|
<h1>Loading Pokédex</h1>
|
||||||
|
<span class="loading loading-spinner loading-xl"></span>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
// Supabase-based CatchRecord interface
|
import mongoose, { Schema, Document, Types } from 'mongoose';
|
||||||
export interface CatchRecord {
|
|
||||||
_id: string; // Maps to Supabase 'id' field for frontend compatibility
|
export interface CatchRecord extends Document {
|
||||||
userId: string;
|
userId: string;
|
||||||
pokemonId: string;
|
pokedexEntryId: Types.ObjectId;
|
||||||
pokedexId: string;
|
|
||||||
haveToEvolve: boolean;
|
haveToEvolve: boolean;
|
||||||
caught: boolean;
|
caught: boolean;
|
||||||
inHome: boolean;
|
inHome: boolean;
|
||||||
@@ -11,18 +10,15 @@ export interface CatchRecord {
|
|||||||
personalNotes: string;
|
personalNotes: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database record type for Supabase
|
const catchRecordSchema = new Schema<CatchRecord>({
|
||||||
export interface CatchRecordDB {
|
userId: String,
|
||||||
id: string;
|
pokedexEntryId: { type: Schema.Types.ObjectId, ref: 'PokedexEntry', required: true },
|
||||||
userId: string;
|
haveToEvolve: { type: Boolean, default: false },
|
||||||
/** Numeric foreign key in database (references `pokemon.id`) */
|
caught: { type: Boolean, default: false },
|
||||||
pokemonId: number;
|
inHome: { type: Boolean, default: false },
|
||||||
pokedexId: string; // NEW: Foreign key to pokedexes table
|
hasGigantamaxed: { type: Boolean, default: false },
|
||||||
haveToEvolve: boolean;
|
personalNotes: String
|
||||||
caught: boolean;
|
});
|
||||||
inHome: boolean;
|
|
||||||
hasGigantamaxed: boolean;
|
const CatchRecordModel = mongoose.model<CatchRecord>('CatchRecord', catchRecordSchema);
|
||||||
personalNotes: string;
|
export default CatchRecordModel;
|
||||||
createdAt: string;
|
|
||||||
updatedAt: string;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,5 +3,5 @@ import { type CatchRecord } from './CatchRecord';
|
|||||||
|
|
||||||
export interface CombinedData {
|
export interface CombinedData {
|
||||||
pokedexEntry: PokedexEntry;
|
pokedexEntry: PokedexEntry;
|
||||||
catchRecord: CatchRecord | null;
|
catchRecord: CatchRecord;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
export interface Pokedex {
|
|
||||||
_id: string;
|
|
||||||
userId: string;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
isLivingDex: boolean;
|
|
||||||
isShinyDex: boolean;
|
|
||||||
isOriginDex: boolean;
|
|
||||||
isFormDex: boolean;
|
|
||||||
gameScope: string | null;
|
|
||||||
dexScopes: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PokedexDB {
|
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
name: string;
|
|
||||||
description: string;
|
|
||||||
isLivingDex: boolean;
|
|
||||||
isShinyDex: boolean;
|
|
||||||
isOriginDex: boolean;
|
|
||||||
isFormDex: boolean;
|
|
||||||
gameScope: string | null;
|
|
||||||
createdAt: string;
|
|
||||||
updatedAt: string;
|
|
||||||
}
|
|
||||||
@@ -1,41 +1,51 @@
|
|||||||
// Supabase-based PokedexEntry interface
|
import mongoose, { Schema, Document } from 'mongoose';
|
||||||
export type CatchInformationItem = {
|
|
||||||
game: string;
|
|
||||||
location: string;
|
|
||||||
notes: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface PokedexEntry {
|
export interface PokedexEntry extends Document {
|
||||||
_id: string; // Maps to Supabase 'id' field for frontend compatibility
|
|
||||||
pokedexNumber: number;
|
pokedexNumber: number;
|
||||||
|
boxPlacement: { box: number; row: number; column: number };
|
||||||
|
boxPlacementForms: { box: number; row: number; column: number };
|
||||||
pokemon: string;
|
pokemon: string;
|
||||||
form: string;
|
form: string;
|
||||||
spriteKey: string;
|
|
||||||
canGigantamax: boolean;
|
canGigantamax: boolean;
|
||||||
regionToCatchIn: string;
|
regionToCatchIn: string;
|
||||||
gamesToCatchIn: string[];
|
gamesToCatchIn: string[];
|
||||||
regionToEvolveIn: string;
|
regionToEvolveIn: string;
|
||||||
evolutionInformation: string;
|
evolutionInformation: string;
|
||||||
catchInformation: Array<string | CatchInformationItem>;
|
catchInformation: [
|
||||||
|
{
|
||||||
|
game: string;
|
||||||
|
location: string;
|
||||||
notes: string;
|
notes: string;
|
||||||
// Note: Regional dex numbers stored in separate regional_dex_numbers table
|
}
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database record type for Supabase
|
const pokedexEntrySchema = new Schema<PokedexEntry>({
|
||||||
export interface PokedexEntryDB {
|
pokedexNumber: Number,
|
||||||
id: number;
|
boxPlacement: {
|
||||||
pokedexNumber: number;
|
box: Number,
|
||||||
pokemon: string;
|
row: Number,
|
||||||
form: string | null;
|
column: Number
|
||||||
spriteKey: string | null;
|
},
|
||||||
canGigantamax: boolean;
|
boxPlacementForms: {
|
||||||
regionToCatchIn: string | null;
|
box: Number,
|
||||||
gamesToCatchIn: string[] | null;
|
row: Number,
|
||||||
regionToEvolveIn: string | null;
|
column: Number
|
||||||
evolutionInformation: string | null;
|
},
|
||||||
catchInformation: string[] | null;
|
pokemon: String,
|
||||||
notes: string | null;
|
form: String,
|
||||||
// Note: Regional dex numbers stored in separate regional_dex_numbers table
|
canGigantamax: Boolean,
|
||||||
createdAt: string;
|
regionToCatchIn: String,
|
||||||
updatedAt: string;
|
gamesToCatchIn: Array<string>,
|
||||||
}
|
regionToEvolveIn: String,
|
||||||
|
evolutionInformation: String,
|
||||||
|
catchInformation: [
|
||||||
|
{
|
||||||
|
game: String,
|
||||||
|
location: String,
|
||||||
|
notes: String
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
export default mongoose.model<PokedexEntry>('PokedexEntry', pokedexEntrySchema);
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
export type ExportProvider = 'google_drive' | 'dropbox';
|
|
||||||
|
|
||||||
export interface PokedexExportIntegration {
|
|
||||||
_id: string;
|
|
||||||
userId: string;
|
|
||||||
pokedexId: string | null;
|
|
||||||
provider: ExportProvider;
|
|
||||||
enabled: boolean;
|
|
||||||
fileName: string | null;
|
|
||||||
folderId: string | null;
|
|
||||||
path: string | null;
|
|
||||||
accessToken: string;
|
|
||||||
refreshToken: string | null;
|
|
||||||
accessTokenExpiresAt: string | null;
|
|
||||||
metadata: Record<string, unknown> | null;
|
|
||||||
lastExportedAt: string | null;
|
|
||||||
lastError: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PokedexExportIntegrationDB {
|
|
||||||
id: string;
|
|
||||||
userId: string;
|
|
||||||
pokedexId: string | null;
|
|
||||||
provider: ExportProvider;
|
|
||||||
enabled: boolean;
|
|
||||||
fileName: string | null;
|
|
||||||
folderId: string | null;
|
|
||||||
path: string | null;
|
|
||||||
accessToken: string;
|
|
||||||
refreshToken: string | null;
|
|
||||||
accessTokenExpiresAt: string | null;
|
|
||||||
metadata: Record<string, unknown> | null;
|
|
||||||
lastExportedAt: string | null;
|
|
||||||
lastError: string | null;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import mongoose, { Schema, Document } from 'mongoose';
|
||||||
|
|
||||||
|
export interface PokedexMetadata extends Document {
|
||||||
|
lastModified: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pokedexMetadataSchema = new Schema<PokedexMetadata>({
|
||||||
|
lastModified: {
|
||||||
|
type: Date,
|
||||||
|
default: Date.now
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default mongoose.model<PokedexMetadata>('PokedexMetadata', pokedexMetadataSchema);
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
// Supabase-based RegionGameMapping interface
|
import mongoose, { Schema, Document } from 'mongoose';
|
||||||
export interface RegionGameMapping {
|
|
||||||
id?: number;
|
export interface RegionGameMapping extends Document {
|
||||||
region: string;
|
region: string;
|
||||||
game: string; // Note: Different from MongoDB version which had 'games' array
|
games: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Database record type for Supabase
|
const regionGameMappingSchema = new Schema<RegionGameMapping>({
|
||||||
export interface RegionGameMappingDB {
|
region: String,
|
||||||
id: number;
|
games: Array<string>
|
||||||
region: string;
|
});
|
||||||
game: string;
|
|
||||||
}
|
export default mongoose.model<RegionGameMapping>('RegionGameMapping', regionGameMappingSchema);
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import mongoose, { Schema, Document } from 'mongoose';
|
||||||
|
|
||||||
|
export interface User extends Document {
|
||||||
|
username: string;
|
||||||
|
// Add other user-related fields as needed
|
||||||
|
}
|
||||||
|
|
||||||
|
const userSchema = new Schema<User>({
|
||||||
|
username: String
|
||||||
|
// Add other user-related fields as needed
|
||||||
|
});
|
||||||
|
|
||||||
|
export default mongoose.model<User>('User', userSchema);
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import mongoose, { Schema, Document } from 'mongoose';
|
||||||
|
|
||||||
|
export interface UserCatchEntry extends Document {
|
||||||
|
userId: mongoose.Types.ObjectId; // Reference to the user
|
||||||
|
pokedexEntryId: mongoose.Types.ObjectId; // Reference to the pokedex entry
|
||||||
|
haveToEvolve: boolean;
|
||||||
|
caught: boolean;
|
||||||
|
inHome: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const userCatchEntrySchema = new Schema<UserCatchEntry>({
|
||||||
|
userId: { type: mongoose.Types.ObjectId, ref: 'User' },
|
||||||
|
pokedexEntryId: { type: mongoose.Types.ObjectId, ref: 'PokedexEntry' },
|
||||||
|
haveToEvolve: Boolean,
|
||||||
|
caught: Boolean,
|
||||||
|
inHome: Boolean
|
||||||
|
});
|
||||||
|
|
||||||
|
export default mongoose.model<UserCatchEntry>('UserCatchEntry', userCatchEntrySchema);
|
||||||
@@ -1,235 +1,35 @@
|
|||||||
import type { CatchRecord, CatchRecordDB } from '$lib/models/CatchRecord';
|
import CatchRecordModel, { type CatchRecord } from '$lib/models/CatchRecord';
|
||||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
||||||
|
|
||||||
type PartialExcept<T, K extends keyof T> = Partial<T> & Pick<T, K>;
|
|
||||||
|
|
||||||
class CatchRecordRepository {
|
class CatchRecordRepository {
|
||||||
constructor(
|
|
||||||
private supabase: SupabaseClient,
|
|
||||||
private userId: string,
|
|
||||||
private pokedexId: string
|
|
||||||
) {}
|
|
||||||
|
|
||||||
// Transform Supabase data to frontend format (minimal transformation)
|
|
||||||
private transformCatchRecord(record: CatchRecordDB): CatchRecord {
|
|
||||||
return {
|
|
||||||
_id: record.id,
|
|
||||||
userId: record.userId,
|
|
||||||
pokemonId: record.pokemonId.toString(),
|
|
||||||
pokedexId: record.pokedexId,
|
|
||||||
haveToEvolve: record.haveToEvolve,
|
|
||||||
caught: record.caught,
|
|
||||||
inHome: record.inHome,
|
|
||||||
hasGigantamaxed: record.hasGigantamaxed,
|
|
||||||
personalNotes: record.personalNotes
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform frontend data to database format (minimal transformation)
|
|
||||||
private transformToDatabase(data: Partial<CatchRecord>): Partial<CatchRecordDB> {
|
|
||||||
const dbData: Partial<CatchRecordDB> = {};
|
|
||||||
if (data.pokemonId !== undefined && data.pokemonId !== null) {
|
|
||||||
const numericId = Number(data.pokemonId);
|
|
||||||
if (isNaN(numericId)) {
|
|
||||||
throw new Error(`Invalid pokemonId: ${data.pokemonId}`);
|
|
||||||
}
|
|
||||||
dbData.pokemonId = numericId;
|
|
||||||
}
|
|
||||||
if (data.pokedexId !== undefined) dbData.pokedexId = data.pokedexId;
|
|
||||||
if (data.haveToEvolve !== undefined) dbData.haveToEvolve = data.haveToEvolve;
|
|
||||||
if (data.caught !== undefined) dbData.caught = data.caught;
|
|
||||||
if (data.inHome !== undefined) dbData.inHome = data.inHome;
|
|
||||||
if (data.hasGigantamaxed !== undefined) dbData.hasGigantamaxed = data.hasGigantamaxed;
|
|
||||||
if (data.personalNotes !== undefined) dbData.personalNotes = data.personalNotes;
|
|
||||||
|
|
||||||
return dbData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bulk upsert catch records in a single request when possible.
|
|
||||||
*
|
|
||||||
* Requires a unique constraint matching the `onConflict` columns.
|
|
||||||
* If the database is not configured with that constraint, the caller should
|
|
||||||
* catch the error and fall back to per-record upserts.
|
|
||||||
*/
|
|
||||||
async bulkUpsert(
|
|
||||||
records: Array<PartialExcept<CatchRecord, 'pokemonId'>>
|
|
||||||
): Promise<CatchRecord[]> {
|
|
||||||
if (records.length === 0) return [];
|
|
||||||
|
|
||||||
const dbRows: Partial<CatchRecordDB>[] = records.map((r, index) => {
|
|
||||||
if (r.pokemonId === undefined || r.pokemonId === null || r.pokemonId === '') {
|
|
||||||
throw new Error(
|
|
||||||
`CatchRecordRepository.bulkUpsert: record at index ${index} is missing required field "pokemonId"`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preserve repository scoping; if a caller supplies ids, they must match the repo scope.
|
|
||||||
if (r.userId !== undefined && r.userId !== this.userId) {
|
|
||||||
throw new Error(
|
|
||||||
`CatchRecordRepository.bulkUpsert: record at index ${index} has userId "${r.userId}" but repository is scoped to "${this.userId}"`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (r.pokedexId !== undefined && r.pokedexId !== this.pokedexId) {
|
|
||||||
throw new Error(
|
|
||||||
`CatchRecordRepository.bulkUpsert: record at index ${index} has pokedexId "${r.pokedexId}" but repository is scoped to "${this.pokedexId}"`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const mapped = this.transformToDatabase(r);
|
|
||||||
// Enforce repo scope after mapping so per-record input cannot override it.
|
|
||||||
mapped.userId = this.userId;
|
|
||||||
mapped.pokedexId = this.pokedexId;
|
|
||||||
|
|
||||||
if (mapped.pokemonId === undefined || mapped.pokemonId === null) {
|
|
||||||
throw new Error(
|
|
||||||
`CatchRecordRepository.bulkUpsert: record at index ${index} produced no pokemonId after transform`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mapped;
|
|
||||||
});
|
|
||||||
|
|
||||||
const { data: result, error } = await this.supabase
|
|
||||||
.from('catch_records')
|
|
||||||
.upsert(dbRows, {
|
|
||||||
onConflict: '"userId","pokedexId","pokemonId"'
|
|
||||||
})
|
|
||||||
.select();
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Supabase error bulk upserting catch records:', error);
|
|
||||||
throw new Error(`Failed to bulk upsert catch records: ${error.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (result ?? []).map((row) => this.transformCatchRecord(row));
|
|
||||||
}
|
|
||||||
|
|
||||||
async findById(id: string): Promise<CatchRecord | null> {
|
async findById(id: string): Promise<CatchRecord | null> {
|
||||||
const { data, error } = await this.supabase
|
return CatchRecordModel.findById(id).exec();
|
||||||
.from('catch_records')
|
|
||||||
.select('*')
|
|
||||||
.eq('id', id)
|
|
||||||
.eq('userId', this.userId)
|
|
||||||
.eq('pokedexId', this.pokedexId)
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error || !data) return null;
|
|
||||||
return this.transformCatchRecord(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(): Promise<CatchRecord[]> {
|
async findAll(): Promise<CatchRecord[]> {
|
||||||
const { data, error } = await this.supabase
|
return CatchRecordModel.find().exec();
|
||||||
.from('catch_records')
|
|
||||||
.select('*')
|
|
||||||
.eq('userId', this.userId)
|
|
||||||
.eq('pokedexId', this.pokedexId);
|
|
||||||
|
|
||||||
if (error || !data) return [];
|
|
||||||
return data.map((record) => this.transformCatchRecord(record));
|
|
||||||
}
|
|
||||||
|
|
||||||
async findByUserId(userId: string): Promise<CatchRecord[]> {
|
|
||||||
const { data, error } = await this.supabase
|
|
||||||
.from('catch_records')
|
|
||||||
.select('*')
|
|
||||||
.eq('userId', userId)
|
|
||||||
.eq('pokedexId', this.pokedexId);
|
|
||||||
|
|
||||||
if (error || !data) return [];
|
|
||||||
return data.map((record) => this.transformCatchRecord(record));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(data: Partial<CatchRecord>): Promise<CatchRecord> {
|
async create(data: Partial<CatchRecord>): Promise<CatchRecord> {
|
||||||
const dbData = {
|
return CatchRecordModel.create(data);
|
||||||
userId: this.userId,
|
|
||||||
pokedexId: this.pokedexId,
|
|
||||||
...this.transformToDatabase(data)
|
|
||||||
};
|
|
||||||
|
|
||||||
const { data: result, error } = await this.supabase
|
|
||||||
.from('catch_records')
|
|
||||||
.insert(dbData)
|
|
||||||
.select()
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Supabase error creating catch record:', error);
|
|
||||||
throw new Error(`Failed to create catch record: ${error.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
throw new Error('Failed to create catch record: No result returned');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.transformCatchRecord(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(id: string, data: Partial<CatchRecord>): Promise<CatchRecord | null> {
|
async update(id: string, data: Partial<CatchRecord>): Promise<CatchRecord | null> {
|
||||||
const dbData = this.transformToDatabase(data);
|
return CatchRecordModel.findByIdAndUpdate(id, data, { new: true }).exec();
|
||||||
|
|
||||||
const { data: result, error } = await this.supabase
|
|
||||||
.from('catch_records')
|
|
||||||
.update(dbData)
|
|
||||||
.eq('id', id)
|
|
||||||
.eq('userId', this.userId)
|
|
||||||
.eq('pokedexId', this.pokedexId)
|
|
||||||
.select()
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error || !result) return null;
|
|
||||||
return this.transformCatchRecord(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string): Promise<void> {
|
async delete(id: string): Promise<void> {
|
||||||
const { error } = await this.supabase
|
await CatchRecordModel.findByIdAndDelete(id).exec();
|
||||||
.from('catch_records')
|
|
||||||
.delete()
|
|
||||||
.eq('id', id)
|
|
||||||
.eq('userId', this.userId)
|
|
||||||
.eq('pokedexId', this.pokedexId);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error deleting catch record:', error);
|
|
||||||
throw new Error(`Failed to delete catch record: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async upsert(data: Partial<CatchRecord>): Promise<CatchRecord | null> {
|
async upsert(data: Partial<CatchRecord>): Promise<CatchRecord | null> {
|
||||||
if (data._id) {
|
if (data._id) {
|
||||||
return this.update(data._id, data);
|
// Update existing record
|
||||||
} else if (data.pokemonId) {
|
return CatchRecordModel.findByIdAndUpdate(data._id, data, { new: true }).exec();
|
||||||
// Try to find existing record for this user, pokemon, and pokedex
|
|
||||||
const existing = await this.findByUserAndPokemon(this.userId, data.pokemonId, this.pokedexId);
|
|
||||||
if (existing) {
|
|
||||||
return this.update(existing._id, data);
|
|
||||||
} else {
|
} else {
|
||||||
return this.create(data);
|
// Create new record
|
||||||
|
return CatchRecordModel.create(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.create(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
async findByUserAndPokemon(
|
|
||||||
userId: string,
|
|
||||||
pokemonId: string,
|
|
||||||
pokedexId: string
|
|
||||||
): Promise<CatchRecord | null> {
|
|
||||||
const numericId = Number(pokemonId);
|
|
||||||
if (isNaN(numericId)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const { data, error } = await this.supabase
|
|
||||||
.from('catch_records')
|
|
||||||
.select('*')
|
|
||||||
.eq('userId', userId)
|
|
||||||
.eq('pokemonId', numericId)
|
|
||||||
.eq('pokedexId', pokedexId)
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error || !data) return null;
|
|
||||||
return this.transformCatchRecord(data);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CatchRecordRepository;
|
export default CatchRecordRepository;
|
||||||
|
|||||||
@@ -1,495 +1,163 @@
|
|||||||
import { type PokedexEntry, type PokedexEntryDB } from '$lib/models/PokedexEntry';
|
import PokedexEntryModel, { type PokedexEntry } from '$lib/models/PokedexEntry';
|
||||||
import { type CatchRecord, type CatchRecordDB } from '$lib/models/CatchRecord';
|
import CatchRecordModel, { type CatchRecord } from '$lib/models/CatchRecord';
|
||||||
import { type CombinedData } from '$lib/models/CombinedData';
|
import { CombinedData } from '$lib/models/CombinedData';
|
||||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
||||||
|
|
||||||
// Raw row from game_pokedex_entry_details includes extra ordering columns not in PokedexEntryDB.
|
|
||||||
type RawDexEntry = PokedexEntryDB & {
|
|
||||||
dexNumber: number;
|
|
||||||
dexSortOrder: number;
|
|
||||||
formSortBucket: number;
|
|
||||||
formSortRegionOrder: number;
|
|
||||||
formSortRegionalSub: number;
|
|
||||||
formSortLabel: string;
|
|
||||||
unownSortOrder: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CombinedDataRepository {
|
class CombinedDataRepository {
|
||||||
private static readonly MAX_ROWS_PER_REQUEST = 1000;
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private supabase: SupabaseClient,
|
|
||||||
private userId: string | null,
|
|
||||||
private pokedexId: string | null
|
|
||||||
) {}
|
|
||||||
|
|
||||||
// Transform Supabase data to match frontend expectations (minimal transformation)
|
|
||||||
private transformPokedexEntry(entry: PokedexEntryDB): PokedexEntry {
|
|
||||||
return {
|
|
||||||
_id: entry.id.toString(),
|
|
||||||
pokedexNumber: entry.pokedexNumber,
|
|
||||||
pokemon: entry.pokemon,
|
|
||||||
form: entry.form || '',
|
|
||||||
spriteKey: entry.spriteKey || '',
|
|
||||||
canGigantamax: entry.canGigantamax,
|
|
||||||
regionToCatchIn: entry.regionToCatchIn || '',
|
|
||||||
gamesToCatchIn: entry.gamesToCatchIn || [],
|
|
||||||
regionToEvolveIn: entry.regionToEvolveIn || '',
|
|
||||||
evolutionInformation: entry.evolutionInformation || '',
|
|
||||||
catchInformation: entry.catchInformation || [],
|
|
||||||
notes: entry.notes || ''
|
|
||||||
// Note: Regional dex numbers are stored in separate regional_dex_numbers table
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private transformCatchRecord(record: CatchRecordDB): CatchRecord {
|
|
||||||
return {
|
|
||||||
_id: record.id,
|
|
||||||
userId: record.userId,
|
|
||||||
pokemonId: record.pokemonId.toString(),
|
|
||||||
pokedexId: record.pokedexId,
|
|
||||||
haveToEvolve: record.haveToEvolve,
|
|
||||||
caught: record.caught,
|
|
||||||
inHome: record.inHome,
|
|
||||||
hasGigantamaxed: record.hasGigantamaxed,
|
|
||||||
personalNotes: record.personalNotes
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildEntriesQuery(enableForms: boolean, region: string, game: string) {
|
|
||||||
let query = this.supabase.from('pokedex_entries').select('*');
|
|
||||||
|
|
||||||
if (!enableForms) {
|
|
||||||
// Filter to base forms: NULL or 'male' (gendered species), plus Unown "A".
|
|
||||||
query = query.or('form.is.null,form.eq.male,and(pokemon.eq.Unown,form.eq.A)');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (region) {
|
|
||||||
query = query.eq('regionToCatchIn', region);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (game) {
|
|
||||||
query = query.contains('gamesToCatchIn', [game]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stable ordering from the database: national dex, Unown order, base/female/temporal, then form label.
|
|
||||||
query = query
|
|
||||||
.order('pokedexNumber', { ascending: true })
|
|
||||||
.order('unownSortOrder', { ascending: true })
|
|
||||||
.order('formSortBucket', { ascending: true })
|
|
||||||
.order('formSortRegionOrder', { ascending: true })
|
|
||||||
.order('formSortRegionalSub', { ascending: true })
|
|
||||||
.order('formSortLabel', { ascending: true });
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildDexEntriesQuery(dexScopes: string[], enableForms: boolean, region: string) {
|
|
||||||
let query = this.supabase.from('game_pokedex_entry_details').select('*').in('dexId', dexScopes);
|
|
||||||
|
|
||||||
if (!enableForms) {
|
|
||||||
// Filter to base forms: NULL or 'male' (gendered species), plus Unown "A".
|
|
||||||
query = query.or('form.is.null,form.eq.male,and(pokemon.eq.Unown,form.eq.A)');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (region) {
|
|
||||||
query = query.eq('regionToCatchIn', region);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stable ordering: dex order, dex number, Unown order, base/female/temporal, then form label.
|
|
||||||
query = query
|
|
||||||
.order('dexSortOrder', { ascending: true })
|
|
||||||
.order('dexNumber', { ascending: true })
|
|
||||||
.order('unownSortOrder', { ascending: true })
|
|
||||||
.order('formSortBucket', { ascending: true })
|
|
||||||
.order('formSortRegionOrder', { ascending: true })
|
|
||||||
.order('formSortRegionalSub', { ascending: true })
|
|
||||||
.order('formSortLabel', { ascending: true });
|
|
||||||
|
|
||||||
return query;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch all non-base form entries for a game from pokedex_entries, excluding already-seen IDs.
|
|
||||||
// game_pokedex_entries is seeded with base forms only, so forms must be supplemented from here.
|
|
||||||
private async fetchFormsForGame(
|
|
||||||
game: string,
|
|
||||||
region: string,
|
|
||||||
excludeIds: Set<number>
|
|
||||||
): Promise<PokedexEntryDB[]> {
|
|
||||||
const allForms: PokedexEntryDB[] = [];
|
|
||||||
let start = 0;
|
|
||||||
const maxRows = CombinedDataRepository.MAX_ROWS_PER_REQUEST;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const end = start + maxRows - 1;
|
|
||||||
let query = this.supabase.from('pokedex_entries').select('*').not('form', 'is', null);
|
|
||||||
|
|
||||||
if (game) {
|
|
||||||
query = query.contains('gamesToCatchIn', [game]);
|
|
||||||
}
|
|
||||||
if (region) {
|
|
||||||
query = query.eq('regionToCatchIn', region);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data, error } = await query.order('id', { ascending: true }).range(start, end);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error fetching forms for game:', error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data || data.length === 0) break;
|
|
||||||
|
|
||||||
allForms.push(...(data as PokedexEntryDB[]).filter((e) => !excludeIds.has(e.id)));
|
|
||||||
|
|
||||||
if (data.length < maxRows) break;
|
|
||||||
start = end + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return allForms;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async fetchAllDexEntries(
|
|
||||||
dexScopes: string[],
|
|
||||||
enableForms: boolean,
|
|
||||||
region: string,
|
|
||||||
game: string = ''
|
|
||||||
): Promise<PokedexEntryDB[]> {
|
|
||||||
if (dexScopes.length === 0) return [];
|
|
||||||
|
|
||||||
const entries: RawDexEntry[] = [];
|
|
||||||
let start = 0;
|
|
||||||
const maxRows = CombinedDataRepository.MAX_ROWS_PER_REQUEST;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const end = start + maxRows - 1;
|
|
||||||
const { data, error } = await this.buildDexEntriesQuery(dexScopes, enableForms, region).range(
|
|
||||||
start,
|
|
||||||
end
|
|
||||||
);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error finding dex-scoped combined data:', error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data || data.length === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.push(...(data as RawDexEntry[]));
|
|
||||||
|
|
||||||
if (data.length < maxRows) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = end + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// When forms are enabled, game_pokedex_entries only has base forms, so supplement from pokedex_entries.
|
|
||||||
if (!enableForms || !game) {
|
|
||||||
return entries as PokedexEntryDB[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build lookup: pokedexNumber → dex position (from the raw game dex data)
|
|
||||||
const dexInfoByPokedexNumber = new Map<number, { dexNumber: number; dexSortOrder: number }>();
|
|
||||||
for (const entry of entries) {
|
|
||||||
if (!dexInfoByPokedexNumber.has(entry.pokedexNumber)) {
|
|
||||||
dexInfoByPokedexNumber.set(entry.pokedexNumber, {
|
|
||||||
dexNumber: entry.dexNumber ?? 0,
|
|
||||||
dexSortOrder: entry.dexSortOrder ?? 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch forms not already covered by game_pokedex_entries
|
|
||||||
const existingIds = new Set(entries.map((e) => e.id));
|
|
||||||
const formEntries = await this.fetchFormsForGame(game, region, existingIds);
|
|
||||||
|
|
||||||
if (formEntries.length === 0) {
|
|
||||||
return entries as PokedexEntryDB[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Merge and sort: dex entries first (they are the canonical base form for the regional dex),
|
|
||||||
// then supplemented forms. Within each group, sort by form fields.
|
|
||||||
type TaggedEntry = RawDexEntry & { _isDexEntry: boolean };
|
|
||||||
const merged: TaggedEntry[] = [
|
|
||||||
...entries.map((e) => ({ ...e, _isDexEntry: true })),
|
|
||||||
...(formEntries as RawDexEntry[]).map((e) => ({ ...e, _isDexEntry: false }))
|
|
||||||
];
|
|
||||||
|
|
||||||
merged.sort((a, b) => {
|
|
||||||
const aDex = dexInfoByPokedexNumber.get(a.pokedexNumber) ?? {
|
|
||||||
dexNumber: 9999,
|
|
||||||
dexSortOrder: 9999
|
|
||||||
};
|
|
||||||
const bDex = dexInfoByPokedexNumber.get(b.pokedexNumber) ?? {
|
|
||||||
dexNumber: 9999,
|
|
||||||
dexSortOrder: 9999
|
|
||||||
};
|
|
||||||
if (aDex.dexSortOrder !== bDex.dexSortOrder) return aDex.dexSortOrder - bDex.dexSortOrder;
|
|
||||||
if (aDex.dexNumber !== bDex.dexNumber) return aDex.dexNumber - bDex.dexNumber;
|
|
||||||
if ((a.unownSortOrder ?? 0) !== (b.unownSortOrder ?? 0))
|
|
||||||
return (a.unownSortOrder ?? 0) - (b.unownSortOrder ?? 0);
|
|
||||||
// Dex entries (canonical regional base form) sort before supplemented forms.
|
|
||||||
if (a._isDexEntry !== b._isDexEntry) return a._isDexEntry ? -1 : 1;
|
|
||||||
if ((a.formSortBucket ?? 0) !== (b.formSortBucket ?? 0))
|
|
||||||
return (a.formSortBucket ?? 0) - (b.formSortBucket ?? 0);
|
|
||||||
if ((a.formSortRegionOrder ?? 0) !== (b.formSortRegionOrder ?? 0))
|
|
||||||
return (a.formSortRegionOrder ?? 0) - (b.formSortRegionOrder ?? 0);
|
|
||||||
if ((a.formSortRegionalSub ?? 0) !== (b.formSortRegionalSub ?? 0))
|
|
||||||
return (a.formSortRegionalSub ?? 0) - (b.formSortRegionalSub ?? 0);
|
|
||||||
return (a.formSortLabel ?? '').localeCompare(b.formSortLabel ?? '');
|
|
||||||
});
|
|
||||||
|
|
||||||
return merged as PokedexEntryDB[];
|
|
||||||
}
|
|
||||||
|
|
||||||
private dedupeEntries(entries: PokedexEntryDB[]): PokedexEntryDB[] {
|
|
||||||
const seen = new Set<number>();
|
|
||||||
const deduped: PokedexEntryDB[] = [];
|
|
||||||
|
|
||||||
for (const entry of entries) {
|
|
||||||
if (seen.has(entry.id)) continue;
|
|
||||||
seen.add(entry.id);
|
|
||||||
deduped.push(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
return deduped;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async fetchEntriesByRange(
|
|
||||||
from: number,
|
|
||||||
to: number,
|
|
||||||
enableForms: boolean,
|
|
||||||
region: string,
|
|
||||||
game: string
|
|
||||||
): Promise<PokedexEntryDB[]> {
|
|
||||||
const entries: PokedexEntryDB[] = [];
|
|
||||||
let start = from;
|
|
||||||
const maxRows = CombinedDataRepository.MAX_ROWS_PER_REQUEST;
|
|
||||||
|
|
||||||
while (start <= to) {
|
|
||||||
const end = Math.min(to, start + maxRows - 1);
|
|
||||||
const { data, error } = await this.buildEntriesQuery(enableForms, region, game).range(
|
|
||||||
start,
|
|
||||||
end
|
|
||||||
);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error finding paginated combined data:', error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data || data.length === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.push(...data);
|
|
||||||
|
|
||||||
if (data.length < end - start + 1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = end + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async fetchAllEntries(
|
|
||||||
enableForms: boolean,
|
|
||||||
region: string,
|
|
||||||
game: string
|
|
||||||
): Promise<PokedexEntryDB[]> {
|
|
||||||
const entries: PokedexEntryDB[] = [];
|
|
||||||
let start = 0;
|
|
||||||
const maxRows = CombinedDataRepository.MAX_ROWS_PER_REQUEST;
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const end = start + maxRows - 1;
|
|
||||||
const { data, error } = await this.buildEntriesQuery(enableForms, region, game).range(
|
|
||||||
start,
|
|
||||||
end
|
|
||||||
);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error finding combined data:', error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data || data.length === 0) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
entries.push(...data);
|
|
||||||
|
|
||||||
if (data.length < maxRows) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
start = end + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async fetchCatchRecords(entryIds: number[], userId: string): Promise<CatchRecordDB[]> {
|
|
||||||
if (!this.pokedexId) return [];
|
|
||||||
if (entryIds.length === 0) return [];
|
|
||||||
|
|
||||||
const records: CatchRecordDB[] = [];
|
|
||||||
const chunkSize = 1000;
|
|
||||||
|
|
||||||
for (let i = 0; i < entryIds.length; i += chunkSize) {
|
|
||||||
const chunk = entryIds.slice(i, i + chunkSize);
|
|
||||||
const { data, error } = await this.supabase
|
|
||||||
.from('catch_records')
|
|
||||||
.select('*')
|
|
||||||
.eq('userId', userId)
|
|
||||||
.eq('pokedexId', this.pokedexId)
|
|
||||||
.in('pokemonId', chunk);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error loading catch records:', error);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data) {
|
|
||||||
records.push(...data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return records;
|
|
||||||
}
|
|
||||||
|
|
||||||
async findAllCombinedData(
|
async findAllCombinedData(
|
||||||
userId: string,
|
|
||||||
enableForms: boolean = true,
|
enableForms: boolean = true,
|
||||||
region: string = '',
|
region: string = '',
|
||||||
game: string = '',
|
game: string = ''
|
||||||
dexScopes: string[] = []
|
|
||||||
): Promise<CombinedData[]> {
|
): Promise<CombinedData[]> {
|
||||||
const entries =
|
const pipeline: any[] = [
|
||||||
dexScopes.length > 0
|
{
|
||||||
? this.dedupeEntries(await this.fetchAllDexEntries(dexScopes, enableForms, region, game))
|
$lookup: {
|
||||||
: await this.fetchAllEntries(enableForms, region, game);
|
from: 'catchrecords',
|
||||||
|
localField: '_id',
|
||||||
if (!entries || entries.length === 0) {
|
foreignField: 'pokedexEntryId',
|
||||||
return [];
|
as: 'catchRecord'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
// Get catch records for all entries
|
{
|
||||||
let catchRecords: CatchRecordDB[] = [];
|
$unwind: {
|
||||||
if (userId && this.pokedexId) {
|
path: '$catchRecord',
|
||||||
const entryIds = entries.map((entry) => entry.id);
|
preserveNullAndEmptyArrays: true
|
||||||
catchRecords = await this.fetchCatchRecords(entryIds, userId);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$sort: {
|
||||||
|
'boxPlacementForms.box': 1,
|
||||||
|
'boxPlacementForms.row': 1,
|
||||||
|
'boxPlacementForms.column': 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
// Combine the data exactly like master branch
|
if (!enableForms) {
|
||||||
const combinedData = entries.map((entry) => {
|
pipeline.unshift({
|
||||||
const userCatchRecord = catchRecords.find((record) => record.pokemonId === entry.id) || null;
|
$match: {
|
||||||
|
'boxPlacement.box': { $ne: null }
|
||||||
const transformedEntry = this.transformPokedexEntry(entry);
|
}
|
||||||
const transformedCatchRecord = userCatchRecord
|
|
||||||
? this.transformCatchRecord(userCatchRecord)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
pokedexEntry: transformedEntry,
|
|
||||||
catchRecord: transformedCatchRecord
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Box placement is calculated dynamically on the frontend based on the current sort order.
|
if (region.length > 0) {
|
||||||
return combinedData;
|
pipeline.unshift({
|
||||||
|
$match: {
|
||||||
|
regionToCatchIn: region
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game.length > 0) {
|
||||||
|
pipeline.unshift({
|
||||||
|
$match: {
|
||||||
|
gamesToCatchIn: { $in: [game] }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const combinedData: CombinedData[] = await PokedexEntryModel.aggregate(pipeline).exec();
|
||||||
|
|
||||||
|
// Filter out entries with no catch records
|
||||||
|
const filteredData = combinedData.filter((data) => data.catchRecord);
|
||||||
|
|
||||||
|
return filteredData.map((data) => ({
|
||||||
|
pokedexEntry: data as PokedexEntry,
|
||||||
|
catchRecord: data.catchRecord as CatchRecord
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
async findCombinedData(
|
async findCombinedData(
|
||||||
userId: string,
|
|
||||||
page: number = 1,
|
page: number = 1,
|
||||||
limit: number = 20,
|
limit: number = 20,
|
||||||
enableForms: boolean = true,
|
enableForms: boolean = true,
|
||||||
region: string = '',
|
region: string = '',
|
||||||
game: string = '',
|
game: string = ''
|
||||||
dexScopes: string[] = []
|
|
||||||
): Promise<CombinedData[]> {
|
): Promise<CombinedData[]> {
|
||||||
const from = (page - 1) * limit;
|
const skip = (page - 1) * limit;
|
||||||
const to = from + limit - 1;
|
const pipeline: any[] = [
|
||||||
const entries =
|
{
|
||||||
dexScopes.length > 0
|
$lookup: {
|
||||||
? this.dedupeEntries(
|
from: 'catchrecords',
|
||||||
await this.fetchAllDexEntries(dexScopes, enableForms, region, game)
|
localField: '_id',
|
||||||
).slice(from, to + 1)
|
foreignField: 'pokedexEntryId',
|
||||||
: await this.fetchEntriesByRange(from, to, enableForms, region, game);
|
as: 'catchRecord'
|
||||||
|
|
||||||
if (!entries || entries.length === 0) {
|
|
||||||
return [];
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
// Get catch records for these entries
|
{
|
||||||
let catchRecords: CatchRecordDB[] = [];
|
$unwind: {
|
||||||
if (userId && this.pokedexId) {
|
path: '$catchRecord',
|
||||||
const entryIds = entries.map((entry) => entry.id);
|
preserveNullAndEmptyArrays: true
|
||||||
catchRecords = await this.fetchCatchRecords(entryIds, userId);
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
// Combine the data exactly like master branch
|
{
|
||||||
const combinedData = entries.map((entry) => {
|
$sort: {
|
||||||
const userCatchRecord = catchRecords.find((record) => record.pokemonId === entry.id) || null;
|
'boxPlacementForms.box': 1,
|
||||||
|
'boxPlacementForms.row': 1,
|
||||||
const transformedEntry = this.transformPokedexEntry(entry);
|
'boxPlacementForms.column': 1
|
||||||
const transformedCatchRecord = userCatchRecord
|
|
||||||
? this.transformCatchRecord(userCatchRecord)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
pokedexEntry: transformedEntry,
|
|
||||||
catchRecord: transformedCatchRecord
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Box placement is calculated dynamically on the frontend based on the current sort order.
|
|
||||||
return combinedData;
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{ $skip: skip },
|
||||||
|
{ $limit: limit }
|
||||||
|
];
|
||||||
|
|
||||||
async countCombinedData(
|
|
||||||
enableForms: boolean,
|
|
||||||
region: string,
|
|
||||||
game: string,
|
|
||||||
dexScopes: string[] = []
|
|
||||||
): Promise<number> {
|
|
||||||
if (dexScopes.length > 0) {
|
|
||||||
const entries = this.dedupeEntries(
|
|
||||||
await this.fetchAllDexEntries(dexScopes, enableForms, region, game)
|
|
||||||
);
|
|
||||||
return entries.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
let query = this.supabase.from('pokedex_entries').select('id', { count: 'exact', head: true });
|
|
||||||
|
|
||||||
// Apply same filters as in findCombinedData
|
|
||||||
if (!enableForms) {
|
if (!enableForms) {
|
||||||
// Filter to base forms: NULL or 'male' (gendered species), plus Unown "A".
|
pipeline.unshift({
|
||||||
query = query.or('form.is.null,form.eq.male,and(pokemon.eq.Unown,form.eq.A)');
|
$match: {
|
||||||
|
'boxPlacement.box': { $ne: null }
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (region) {
|
if (region.length > 0) {
|
||||||
query = query.eq('regionToCatchIn', region);
|
pipeline.unshift({
|
||||||
|
$match: {
|
||||||
|
regionToCatchIn: region
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game) {
|
if (game.length > 0) {
|
||||||
query = query.contains('gamesToCatchIn', [game]);
|
pipeline.unshift({
|
||||||
|
$match: {
|
||||||
|
gamesToCatchIn: { $in: [game] }
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { count, error } = await query;
|
const combinedData: CombinedData[] = await PokedexEntryModel.aggregate(pipeline).exec();
|
||||||
|
|
||||||
if (error) {
|
// Filter out entries with no catch records
|
||||||
console.error('Error counting combined data:', error);
|
const filteredData = combinedData.filter((data) => data.catchRecord);
|
||||||
return 0;
|
|
||||||
|
return filteredData.map((data) => ({
|
||||||
|
pokedexEntry: data as PokedexEntry,
|
||||||
|
catchRecord: data.catchRecord as CatchRecord
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return count || 0;
|
async countCombinedData(enableForms: boolean, region: string, game: string): Promise<number> {
|
||||||
|
const filter: any = {};
|
||||||
|
|
||||||
|
if (!enableForms) {
|
||||||
|
filter['boxPlacement.box'] = { $ne: null };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (region.length > 0) {
|
||||||
|
filter['regionToCatchIn'] = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (game.length > 0) {
|
||||||
|
filter['gamesToCatchIn'] = { $in: [game] };
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const count = await PokedexEntryModel.countDocuments(filter).exec();
|
||||||
|
return count;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error counting documents:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,145 +1,24 @@
|
|||||||
import {
|
import PokedexEntryModel, { type PokedexEntry } from '$lib/models/PokedexEntry';
|
||||||
type CatchInformationItem,
|
|
||||||
type PokedexEntry,
|
|
||||||
type PokedexEntryDB
|
|
||||||
} from '$lib/models/PokedexEntry';
|
|
||||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
||||||
|
|
||||||
class PokedexEntryRepository {
|
class PokedexEntryRepository {
|
||||||
constructor(private supabase: SupabaseClient) {}
|
|
||||||
|
|
||||||
private parseCatchInformation(
|
|
||||||
values: string[] | null
|
|
||||||
): Array<string | CatchInformationItem> {
|
|
||||||
if (!values) return [];
|
|
||||||
return values.map((value) => {
|
|
||||||
const trimmed = value.trim();
|
|
||||||
if (!trimmed.startsWith('{')) return value;
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(trimmed) as Partial<CatchInformationItem>;
|
|
||||||
if (
|
|
||||||
parsed &&
|
|
||||||
typeof parsed.game === 'string' &&
|
|
||||||
typeof parsed.location === 'string' &&
|
|
||||||
typeof parsed.notes === 'string'
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
game: parsed.game,
|
|
||||||
location: parsed.location,
|
|
||||||
notes: parsed.notes
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private serializeCatchInformation(values: Array<string | CatchInformationItem>): string[] {
|
|
||||||
return values.map((value) => (typeof value === 'string' ? value : JSON.stringify(value)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transform Supabase data to match frontend expectations (minimal transformation)
|
|
||||||
private transformPokedexEntry(entry: PokedexEntryDB): PokedexEntry {
|
|
||||||
return {
|
|
||||||
_id: entry.id.toString(),
|
|
||||||
pokedexNumber: entry.pokedexNumber,
|
|
||||||
pokemon: entry.pokemon,
|
|
||||||
form: entry.form || '',
|
|
||||||
spriteKey: entry.spriteKey || '',
|
|
||||||
canGigantamax: entry.canGigantamax,
|
|
||||||
regionToCatchIn: entry.regionToCatchIn || '',
|
|
||||||
gamesToCatchIn: entry.gamesToCatchIn || [],
|
|
||||||
regionToEvolveIn: entry.regionToEvolveIn || '',
|
|
||||||
evolutionInformation: entry.evolutionInformation || '',
|
|
||||||
catchInformation: this.parseCatchInformation(entry.catchInformation),
|
|
||||||
notes: entry.notes || ''
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async findById(id: string): Promise<PokedexEntry | null> {
|
async findById(id: string): Promise<PokedexEntry | null> {
|
||||||
const { data, error } = await this.supabase
|
return PokedexEntryModel.findById(id).exec();
|
||||||
.from('pokedex_entries')
|
|
||||||
.select('*')
|
|
||||||
.eq('id', id)
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error || !data) return null;
|
|
||||||
return this.transformPokedexEntry(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(): Promise<PokedexEntry[]> {
|
async findAll(): Promise<PokedexEntry[]> {
|
||||||
const { data, error } = await this.supabase
|
return PokedexEntryModel.find().exec();
|
||||||
.from('pokedex_entries')
|
|
||||||
.select('*')
|
|
||||||
.order('pokedexNumber', { ascending: true });
|
|
||||||
|
|
||||||
if (error || !data) return [];
|
|
||||||
return data.map((entry) => this.transformPokedexEntry(entry));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(data: Partial<PokedexEntry>): Promise<PokedexEntry> {
|
async create(data: Partial<PokedexEntry>): Promise<PokedexEntry> {
|
||||||
// Transform to database format (minimal transformation needed)
|
return PokedexEntryModel.create(data);
|
||||||
const dbData: Partial<PokedexEntryDB> = {};
|
|
||||||
if (data.pokedexNumber !== undefined) dbData.pokedexNumber = data.pokedexNumber;
|
|
||||||
if (data.pokemon !== undefined) dbData.pokemon = data.pokemon;
|
|
||||||
if (data.form !== undefined) dbData.form = data.form;
|
|
||||||
if (data.spriteKey !== undefined) dbData.spriteKey = data.spriteKey;
|
|
||||||
if (data.canGigantamax !== undefined) dbData.canGigantamax = data.canGigantamax;
|
|
||||||
if (data.regionToCatchIn !== undefined) dbData.regionToCatchIn = data.regionToCatchIn;
|
|
||||||
if (data.gamesToCatchIn !== undefined) dbData.gamesToCatchIn = data.gamesToCatchIn;
|
|
||||||
if (data.regionToEvolveIn !== undefined) dbData.regionToEvolveIn = data.regionToEvolveIn;
|
|
||||||
if (data.evolutionInformation !== undefined)
|
|
||||||
dbData.evolutionInformation = data.evolutionInformation;
|
|
||||||
if (data.catchInformation !== undefined) {
|
|
||||||
dbData.catchInformation = this.serializeCatchInformation(data.catchInformation);
|
|
||||||
}
|
|
||||||
if (data.notes !== undefined) dbData.notes = data.notes;
|
|
||||||
// Box placement is calculated dynamically - not stored in database
|
|
||||||
|
|
||||||
const { data: result, error } = await this.supabase
|
|
||||||
.from('pokedex_entries')
|
|
||||||
.insert(dbData)
|
|
||||||
.select()
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error || !result) throw new Error('Failed to create pokedex entry');
|
|
||||||
return this.transformPokedexEntry(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(id: string, data: Partial<PokedexEntry>): Promise<PokedexEntry | null> {
|
async update(id: string, data: Partial<PokedexEntry>): Promise<PokedexEntry | null> {
|
||||||
// Transform to database format (minimal transformation needed)
|
return PokedexEntryModel.findByIdAndUpdate(id, data, { new: true }).exec();
|
||||||
const dbData: Partial<PokedexEntryDB> = {};
|
|
||||||
if (data.pokedexNumber !== undefined) dbData.pokedexNumber = data.pokedexNumber;
|
|
||||||
if (data.pokemon !== undefined) dbData.pokemon = data.pokemon;
|
|
||||||
if (data.form !== undefined) dbData.form = data.form;
|
|
||||||
if (data.spriteKey !== undefined) dbData.spriteKey = data.spriteKey;
|
|
||||||
if (data.canGigantamax !== undefined) dbData.canGigantamax = data.canGigantamax;
|
|
||||||
if (data.regionToCatchIn !== undefined) dbData.regionToCatchIn = data.regionToCatchIn;
|
|
||||||
if (data.gamesToCatchIn !== undefined) dbData.gamesToCatchIn = data.gamesToCatchIn;
|
|
||||||
if (data.regionToEvolveIn !== undefined) dbData.regionToEvolveIn = data.regionToEvolveIn;
|
|
||||||
if (data.evolutionInformation !== undefined)
|
|
||||||
dbData.evolutionInformation = data.evolutionInformation;
|
|
||||||
if (data.catchInformation !== undefined) {
|
|
||||||
dbData.catchInformation = this.serializeCatchInformation(data.catchInformation);
|
|
||||||
}
|
|
||||||
if (data.notes !== undefined) dbData.notes = data.notes;
|
|
||||||
// Box placement is calculated dynamically - not stored in database
|
|
||||||
|
|
||||||
const { data: result, error } = await this.supabase
|
|
||||||
.from('pokedex_entries')
|
|
||||||
.update(dbData)
|
|
||||||
.eq('id', id)
|
|
||||||
.select()
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error || !result) return null;
|
|
||||||
return this.transformPokedexEntry(result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string): Promise<void> {
|
async delete(id: string): Promise<void> {
|
||||||
await this.supabase.from('pokedex_entries').delete().eq('id', id);
|
await PokedexEntryModel.findByIdAndDelete(id).exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,158 +0,0 @@
|
|||||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
||||||
import type {
|
|
||||||
PokedexExportIntegration,
|
|
||||||
PokedexExportIntegrationDB
|
|
||||||
} from '$lib/models/PokedexExportIntegration';
|
|
||||||
|
|
||||||
class PokedexExportIntegrationRepository {
|
|
||||||
constructor(
|
|
||||||
private supabase: SupabaseClient,
|
|
||||||
private userId: string,
|
|
||||||
private pokedexId: string | null
|
|
||||||
) {}
|
|
||||||
|
|
||||||
private transform(db: PokedexExportIntegrationDB): PokedexExportIntegration {
|
|
||||||
return {
|
|
||||||
_id: db.id,
|
|
||||||
userId: db.userId,
|
|
||||||
pokedexId: db.pokedexId,
|
|
||||||
provider: db.provider,
|
|
||||||
enabled: db.enabled,
|
|
||||||
fileName: db.fileName,
|
|
||||||
folderId: db.folderId,
|
|
||||||
path: db.path,
|
|
||||||
accessToken: db.accessToken,
|
|
||||||
refreshToken: db.refreshToken,
|
|
||||||
accessTokenExpiresAt: db.accessTokenExpiresAt,
|
|
||||||
metadata: db.metadata,
|
|
||||||
lastExportedAt: db.lastExportedAt,
|
|
||||||
lastError: db.lastError
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private baseQuery() {
|
|
||||||
return this.supabase.from('pokedex_export_integrations').select('*').eq('userId', this.userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
private addPokedexScope(query: ReturnType<SupabaseClient['from']>) {
|
|
||||||
if (this.pokedexId) {
|
|
||||||
return query.eq('pokedexId', this.pokedexId);
|
|
||||||
}
|
|
||||||
return query.is('pokedexId', null);
|
|
||||||
}
|
|
||||||
|
|
||||||
async listEnabled(): Promise<PokedexExportIntegration[]> {
|
|
||||||
const { data, error } = await this.addPokedexScope(this.baseQuery()).eq('enabled', true);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Failed to load export integrations:', error);
|
|
||||||
throw new Error(`Failed to load export integrations: ${error.message}`);
|
|
||||||
}
|
|
||||||
if (!data) return [];
|
|
||||||
return data.map((row) => this.transform(row));
|
|
||||||
}
|
|
||||||
|
|
||||||
async listAll(): Promise<PokedexExportIntegration[]> {
|
|
||||||
const { data, error } = await this.addPokedexScope(this.baseQuery());
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Failed to load export integrations:', error);
|
|
||||||
throw new Error(`Failed to load export integrations: ${error.message}`);
|
|
||||||
}
|
|
||||||
if (!data) return [];
|
|
||||||
return data.map((row) => this.transform(row));
|
|
||||||
}
|
|
||||||
|
|
||||||
async upsert(
|
|
||||||
data: Partial<PokedexExportIntegrationDB> &
|
|
||||||
Pick<PokedexExportIntegrationDB, 'provider'>
|
|
||||||
): Promise<PokedexExportIntegration> {
|
|
||||||
const payload: Partial<PokedexExportIntegrationDB> = {
|
|
||||||
userId: this.userId,
|
|
||||||
pokedexId: null,
|
|
||||||
...data
|
|
||||||
};
|
|
||||||
const { data: result, error } = await this.supabase
|
|
||||||
.from('pokedex_export_integrations')
|
|
||||||
.upsert(payload, {
|
|
||||||
onConflict: 'userId,provider'
|
|
||||||
})
|
|
||||||
.select()
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Failed to upsert export integration:', error);
|
|
||||||
throw new Error(`Failed to save export integration: ${error.message}`);
|
|
||||||
}
|
|
||||||
if (!result) {
|
|
||||||
throw new Error('Failed to save export integration: No result returned');
|
|
||||||
}
|
|
||||||
return this.transform(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
async listEnabledForPokedexOrUser(): Promise<PokedexExportIntegration[]> {
|
|
||||||
const base = this.supabase
|
|
||||||
.from('pokedex_export_integrations')
|
|
||||||
.select('*')
|
|
||||||
.eq('userId', this.userId)
|
|
||||||
.eq('enabled', true);
|
|
||||||
const query = this.pokedexId
|
|
||||||
? base.or(`pokedexId.eq.${this.pokedexId},pokedexId.is.null`)
|
|
||||||
: base.is('pokedexId', null);
|
|
||||||
const { data, error } = await query;
|
|
||||||
if (error) {
|
|
||||||
console.error('Failed to load export integrations:', error);
|
|
||||||
throw new Error(`Failed to load export integrations: ${error.message}`);
|
|
||||||
}
|
|
||||||
if (!data) return [];
|
|
||||||
return data.map((row) => this.transform(row));
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateTokens(
|
|
||||||
id: string,
|
|
||||||
patch: {
|
|
||||||
accessToken?: string;
|
|
||||||
refreshToken?: string | null;
|
|
||||||
accessTokenExpiresAt?: string | null;
|
|
||||||
}
|
|
||||||
): Promise<void> {
|
|
||||||
const query = this.supabase
|
|
||||||
.from('pokedex_export_integrations')
|
|
||||||
.update(patch)
|
|
||||||
.eq('id', id)
|
|
||||||
.eq('userId', this.userId);
|
|
||||||
const { error } = this.pokedexId
|
|
||||||
? await query.eq('pokedexId', this.pokedexId)
|
|
||||||
: await query.is('pokedexId', null);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Failed to update export integration tokens:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async updateExportStatus(
|
|
||||||
id: string,
|
|
||||||
patch: {
|
|
||||||
lastExportedAt?: string | null;
|
|
||||||
lastError?: string | null;
|
|
||||||
metadata?: Record<string, unknown> | null;
|
|
||||||
folderId?: string | null;
|
|
||||||
path?: string | null;
|
|
||||||
}
|
|
||||||
): Promise<void> {
|
|
||||||
const query = this.supabase
|
|
||||||
.from('pokedex_export_integrations')
|
|
||||||
.update(patch)
|
|
||||||
.eq('id', id)
|
|
||||||
.eq('userId', this.userId);
|
|
||||||
const { error } = this.pokedexId
|
|
||||||
? await query.eq('pokedexId', this.pokedexId)
|
|
||||||
: await query.is('pokedexId', null);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Failed to update export integration status:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PokedexExportIntegrationRepository;
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
import type { Pokedex, PokedexDB } from '$lib/models/Pokedex';
|
|
||||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
||||||
|
|
||||||
class PokedexRepository {
|
|
||||||
constructor(
|
|
||||||
private supabase: SupabaseClient,
|
|
||||||
private userId: string
|
|
||||||
) {}
|
|
||||||
|
|
||||||
private transform(db: PokedexDB, dexScopes: string[] = []): Pokedex {
|
|
||||||
return {
|
|
||||||
_id: db.id,
|
|
||||||
userId: db.userId,
|
|
||||||
name: db.name,
|
|
||||||
description: db.description || '',
|
|
||||||
isLivingDex: db.isLivingDex,
|
|
||||||
isShinyDex: db.isShinyDex,
|
|
||||||
isOriginDex: db.isOriginDex,
|
|
||||||
isFormDex: db.isFormDex,
|
|
||||||
gameScope: db.gameScope,
|
|
||||||
dexScopes
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private transformToDatabase(data: Partial<Pokedex>): Partial<PokedexDB> {
|
|
||||||
const dbData: Partial<PokedexDB> = {};
|
|
||||||
if (data.name !== undefined) dbData.name = data.name;
|
|
||||||
if (data.description !== undefined) dbData.description = data.description;
|
|
||||||
if (data.isLivingDex !== undefined) dbData.isLivingDex = data.isLivingDex;
|
|
||||||
if (data.isShinyDex !== undefined) dbData.isShinyDex = data.isShinyDex;
|
|
||||||
if (data.isOriginDex !== undefined) dbData.isOriginDex = data.isOriginDex;
|
|
||||||
if (data.isFormDex !== undefined) dbData.isFormDex = data.isFormDex;
|
|
||||||
if (data.gameScope !== undefined) dbData.gameScope = data.gameScope;
|
|
||||||
return dbData;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async fetchDexScopesMap(pokedexIds: string[]): Promise<Map<string, string[]>> {
|
|
||||||
if (pokedexIds.length === 0) return new Map();
|
|
||||||
const { data, error } = await this.supabase
|
|
||||||
.from('pokedex_dex_scopes')
|
|
||||||
.select('pokedexId, dexId')
|
|
||||||
.in('pokedexId', pokedexIds);
|
|
||||||
|
|
||||||
if (error || !data) return new Map();
|
|
||||||
|
|
||||||
const map = new Map<string, string[]>();
|
|
||||||
for (const row of data) {
|
|
||||||
if (!map.has(row.pokedexId)) map.set(row.pokedexId, []);
|
|
||||||
map.get(row.pokedexId)?.push(row.dexId);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
async findById(id: string): Promise<Pokedex | null> {
|
|
||||||
const { data, error } = await this.supabase
|
|
||||||
.from('pokedexes')
|
|
||||||
.select('*')
|
|
||||||
.eq('id', id)
|
|
||||||
.eq('userId', this.userId)
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error || !data) return null;
|
|
||||||
const dexScopesMap = await this.fetchDexScopesMap([data.id]);
|
|
||||||
return this.transform(data, dexScopesMap.get(data.id) || []);
|
|
||||||
}
|
|
||||||
|
|
||||||
async findAll(): Promise<Pokedex[]> {
|
|
||||||
const { data, error } = await this.supabase
|
|
||||||
.from('pokedexes')
|
|
||||||
.select('*')
|
|
||||||
.eq('userId', this.userId)
|
|
||||||
.order('createdAt', { ascending: true });
|
|
||||||
|
|
||||||
if (error || !data) return [];
|
|
||||||
const dexScopesMap = await this.fetchDexScopesMap(data.map((d) => d.id));
|
|
||||||
return data.map((d) => this.transform(d, dexScopesMap.get(d.id) || []));
|
|
||||||
}
|
|
||||||
|
|
||||||
async create(data: Partial<Pokedex>): Promise<Pokedex> {
|
|
||||||
const dbData = {
|
|
||||||
userId: this.userId,
|
|
||||||
...this.transformToDatabase(data)
|
|
||||||
};
|
|
||||||
|
|
||||||
const { data: result, error } = await this.supabase
|
|
||||||
.from('pokedexes')
|
|
||||||
.insert(dbData)
|
|
||||||
.select()
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error creating pokedex:', error);
|
|
||||||
// Preserve the Supabase error code so the API layer can map to a user-friendly response.
|
|
||||||
throw Object.assign(new Error(`Failed to create pokedex: ${error.message}`), {
|
|
||||||
code: error.code
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
throw new Error('Failed to create pokedex: No result returned');
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.transform(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
async update(id: string, data: Partial<Pokedex>): Promise<Pokedex | null> {
|
|
||||||
const dbData = this.transformToDatabase(data);
|
|
||||||
|
|
||||||
const { data: result, error } = await this.supabase
|
|
||||||
.from('pokedexes')
|
|
||||||
.update(dbData)
|
|
||||||
.eq('id', id)
|
|
||||||
.eq('userId', this.userId)
|
|
||||||
.select()
|
|
||||||
.single();
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error updating pokedex:', error);
|
|
||||||
throw Object.assign(new Error(`Failed to update pokedex: ${error.message}`), {
|
|
||||||
code: error.code
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (!result) return null;
|
|
||||||
return this.transform(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
async delete(id: string): Promise<void> {
|
|
||||||
const { error } = await this.supabase
|
|
||||||
.from('pokedexes')
|
|
||||||
.delete()
|
|
||||||
.eq('id', id)
|
|
||||||
.eq('userId', this.userId);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error deleting pokedex:', error);
|
|
||||||
throw new Error(`Failed to delete pokedex: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PokedexRepository;
|
|
||||||
@@ -1,38 +1,24 @@
|
|||||||
import type { RegionGameMapping } from '$lib/models/RegionGameMapping';
|
import RegionGameMappingModel, { type RegionGameMapping } from '$lib/models/RegionGameMapping';
|
||||||
|
|
||||||
class RegionGameMappingRepository {
|
class RegionGameMappingRepository {
|
||||||
async findById(id: string): Promise<RegionGameMapping | null> {
|
async findById(id: string): Promise<RegionGameMapping | null> {
|
||||||
void id;
|
return RegionGameMappingModel.findById(id).exec();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAll(): Promise<RegionGameMapping[]> {
|
async findAll(): Promise<RegionGameMapping[]> {
|
||||||
return [];
|
return RegionGameMappingModel.find().exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
async create(data: Partial<RegionGameMapping>): Promise<RegionGameMapping | null> {
|
async create(data: Partial<RegionGameMapping>): Promise<RegionGameMapping> {
|
||||||
if (!data.region || !data.game) return null;
|
return RegionGameMappingModel.create(data);
|
||||||
return {
|
|
||||||
id: data.id,
|
|
||||||
region: data.region,
|
|
||||||
game: data.game
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async update(id: string, data: Partial<RegionGameMapping>): Promise<RegionGameMapping | null> {
|
async update(id: string, data: Partial<RegionGameMapping>): Promise<RegionGameMapping | null> {
|
||||||
if (!data.region || !data.game) return null;
|
return RegionGameMappingModel.findByIdAndUpdate(id, data, { new: true }).exec();
|
||||||
const normalizedId = Number(id);
|
|
||||||
const resolvedId = Number.isFinite(normalizedId) ? normalizedId : data.id;
|
|
||||||
if (typeof resolvedId !== 'number' || !Number.isFinite(resolvedId)) return null;
|
|
||||||
return {
|
|
||||||
id: resolvedId,
|
|
||||||
region: data.region,
|
|
||||||
game: data.game
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(id: string): Promise<void> {
|
async delete(id: string): Promise<void> {
|
||||||
void id;
|
await RegionGameMappingModel.findByIdAndDelete(id).exec();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
||||||
import type { Pokedex } from '$lib/models/Pokedex';
|
|
||||||
|
|
||||||
type GameDexRow = {
|
|
||||||
id: string;
|
|
||||||
displayName: string;
|
|
||||||
sortOrder: number;
|
|
||||||
isDlc: boolean;
|
|
||||||
parentDexId: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
type GameSummary = {
|
|
||||||
displayName: string;
|
|
||||||
releaseYear: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
type GameDexRowWithGame = GameDexRow & {
|
|
||||||
games: GameSummary | GameSummary[] | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
async function getGameIdForScope(
|
|
||||||
supabase: SupabaseClient,
|
|
||||||
gameScope: string
|
|
||||||
): Promise<string | null> {
|
|
||||||
const { data, error } = await supabase
|
|
||||||
.from('games')
|
|
||||||
.select('id')
|
|
||||||
.eq('displayName', gameScope)
|
|
||||||
.maybeSingle();
|
|
||||||
|
|
||||||
if (error || !data) return null;
|
|
||||||
return data.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function resolveDexScopes(
|
|
||||||
supabase: SupabaseClient,
|
|
||||||
pokedex: Pokedex
|
|
||||||
): Promise<string[]> {
|
|
||||||
if (!pokedex.gameScope) return [];
|
|
||||||
if (pokedex.dexScopes && pokedex.dexScopes.length > 0) {
|
|
||||||
return pokedex.dexScopes;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gameId = await getGameIdForScope(supabase, pokedex.gameScope);
|
|
||||||
if (!gameId) return [];
|
|
||||||
|
|
||||||
const { data, error } = await supabase
|
|
||||||
.from('game_dexes')
|
|
||||||
.select('id')
|
|
||||||
.eq('gameId', gameId)
|
|
||||||
.order('sortOrder', { ascending: true })
|
|
||||||
.order('displayName', { ascending: true });
|
|
||||||
|
|
||||||
if (error || !data) return [];
|
|
||||||
return data.map((row) => row.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function setPokedexDexScopes(
|
|
||||||
supabase: SupabaseClient,
|
|
||||||
pokedexId: string,
|
|
||||||
dexIds: string[]
|
|
||||||
): Promise<void> {
|
|
||||||
const uniqueDexIds = Array.from(new Set(dexIds));
|
|
||||||
|
|
||||||
const { error: deleteError } = await supabase
|
|
||||||
.from('pokedex_dex_scopes')
|
|
||||||
.delete()
|
|
||||||
.eq('pokedexId', pokedexId);
|
|
||||||
|
|
||||||
if (deleteError) {
|
|
||||||
throw new Error(`Failed to clear dex scopes: ${deleteError.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uniqueDexIds.length === 0) return;
|
|
||||||
|
|
||||||
const rows = uniqueDexIds.map((dexId) => ({
|
|
||||||
pokedexId,
|
|
||||||
dexId
|
|
||||||
}));
|
|
||||||
|
|
||||||
const { error: insertError } = await supabase.from('pokedex_dex_scopes').insert(rows);
|
|
||||||
if (insertError) {
|
|
||||||
throw new Error(`Failed to save dex scopes: ${insertError.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function listGameDexes(
|
|
||||||
supabase: SupabaseClient
|
|
||||||
): Promise<{
|
|
||||||
gameDexes: Record<string, GameDexRow[]>;
|
|
||||||
gameOrder: string[];
|
|
||||||
games: { displayName: string; releaseYear: number }[];
|
|
||||||
}> {
|
|
||||||
const { data, error } = await supabase
|
|
||||||
.from('game_dexes')
|
|
||||||
.select('id, displayName, sortOrder, isDlc, parentDexId, games!inner(displayName, releaseYear)')
|
|
||||||
.order('sortOrder', { ascending: true })
|
|
||||||
.order('displayName', { ascending: true });
|
|
||||||
|
|
||||||
if (error || !data) return { gameDexes: {}, gameOrder: [], games: [] };
|
|
||||||
|
|
||||||
const grouped: Record<string, GameDexRow[]> = {};
|
|
||||||
const releaseYears: Record<string, number> = {};
|
|
||||||
const rows = data as GameDexRowWithGame[];
|
|
||||||
for (const row of rows) {
|
|
||||||
const game = Array.isArray(row.games) ? row.games[0] : row.games;
|
|
||||||
if (!game) continue;
|
|
||||||
const gameName = game.displayName;
|
|
||||||
if (!grouped[gameName]) grouped[gameName] = [];
|
|
||||||
if (releaseYears[gameName] == null) {
|
|
||||||
releaseYears[gameName] = game.releaseYear;
|
|
||||||
}
|
|
||||||
grouped[gameName].push({
|
|
||||||
id: row.id,
|
|
||||||
displayName: row.displayName,
|
|
||||||
sortOrder: row.sortOrder,
|
|
||||||
isDlc: row.isDlc,
|
|
||||||
parentDexId: row.parentDexId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const games = Object.keys(grouped)
|
|
||||||
.map((name) => ({
|
|
||||||
displayName: name,
|
|
||||||
releaseYear: releaseYears[name] ?? 0
|
|
||||||
}))
|
|
||||||
.sort((a, b) => {
|
|
||||||
if (a.releaseYear !== b.releaseYear) return b.releaseYear - a.releaseYear;
|
|
||||||
return a.displayName.localeCompare(b.displayName);
|
|
||||||
});
|
|
||||||
|
|
||||||
const gameOrder = games.map((game) => game.displayName);
|
|
||||||
|
|
||||||
return { gameDexes: grouped, gameOrder, games };
|
|
||||||
}
|
|
||||||
@@ -1,493 +0,0 @@
|
|||||||
import { randomUUID } from 'node:crypto';
|
|
||||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
||||||
import type { CombinedData } from '$lib/models/CombinedData';
|
|
||||||
import type { Pokedex } from '$lib/models/Pokedex';
|
|
||||||
import type { ExportProvider, PokedexExportIntegration } from '$lib/models/PokedexExportIntegration';
|
|
||||||
import PokedexRepository from '$lib/repositories/PokedexRepository';
|
|
||||||
import CombinedDataRepository from '$lib/repositories/CombinedDataRepository';
|
|
||||||
import PokedexExportIntegrationRepository from '$lib/repositories/PokedexExportIntegrationRepository';
|
|
||||||
import { resolveDexScopes } from '$lib/services/PokedexDexScopeService';
|
|
||||||
import { getEnv } from '$lib/utils/env';
|
|
||||||
|
|
||||||
type ExportFailure = {
|
|
||||||
integrationId: string;
|
|
||||||
provider: ExportProvider;
|
|
||||||
error: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PokedexExportResult = {
|
|
||||||
attempted: number;
|
|
||||||
succeeded: number;
|
|
||||||
failed: ExportFailure[];
|
|
||||||
};
|
|
||||||
|
|
||||||
function csvEscape(value: unknown): string {
|
|
||||||
if (value === null || value === undefined) return '';
|
|
||||||
const str = String(value);
|
|
||||||
if (/[",\n\r]/.test(str)) {
|
|
||||||
return `"${str.replace(/"/g, '""')}"`;
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
function sanitizeFileName(name: string, fallback: string): string {
|
|
||||||
const trimmed = name.trim();
|
|
||||||
const safe = trimmed.replace(/[\\/:*?"<>|]+/g, '-');
|
|
||||||
if (!safe) return fallback;
|
|
||||||
return safe.endsWith('.csv') ? safe : `${safe}.csv`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildCsv(pokedex: Pokedex, combinedData: CombinedData[]): string {
|
|
||||||
const headers = [
|
|
||||||
'pokemonId',
|
|
||||||
'pokedexNumber',
|
|
||||||
'pokemon',
|
|
||||||
'form',
|
|
||||||
'caught',
|
|
||||||
'haveToEvolve',
|
|
||||||
'inHome',
|
|
||||||
'personalNotes'
|
|
||||||
];
|
|
||||||
|
|
||||||
const lines = [headers.map(csvEscape).join(',')];
|
|
||||||
|
|
||||||
for (const row of combinedData) {
|
|
||||||
const entry = row.pokedexEntry;
|
|
||||||
const catchRecord = row.catchRecord ?? {
|
|
||||||
caught: false,
|
|
||||||
haveToEvolve: false,
|
|
||||||
inHome: false,
|
|
||||||
hasGigantamaxed: false,
|
|
||||||
personalNotes: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
const values = [
|
|
||||||
entry._id,
|
|
||||||
entry.pokedexNumber,
|
|
||||||
entry.pokemon,
|
|
||||||
entry.form || '',
|
|
||||||
catchRecord.caught,
|
|
||||||
catchRecord.haveToEvolve,
|
|
||||||
catchRecord.inHome,
|
|
||||||
catchRecord.personalNotes || ''
|
|
||||||
];
|
|
||||||
|
|
||||||
lines.push(values.map(csvEscape).join(','));
|
|
||||||
}
|
|
||||||
|
|
||||||
return lines.join('\r\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
function shouldRefreshToken(expiresAt: string | null): boolean {
|
|
||||||
if (!expiresAt) return false;
|
|
||||||
const expiry = new Date(expiresAt).getTime();
|
|
||||||
if (!Number.isFinite(expiry)) return false;
|
|
||||||
// Refresh if within 60 seconds of expiry.
|
|
||||||
return expiry - Date.now() < 60_000;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refreshGoogleToken(
|
|
||||||
integration: PokedexExportIntegration,
|
|
||||||
repo: PokedexExportIntegrationRepository
|
|
||||||
): Promise<PokedexExportIntegration> {
|
|
||||||
if (!integration.refreshToken) {
|
|
||||||
throw new Error('Missing Google refresh token');
|
|
||||||
}
|
|
||||||
|
|
||||||
const env = getEnv();
|
|
||||||
const clientId = env.GOOGLE_OAUTH_CLIENT_ID;
|
|
||||||
const clientSecret = env.GOOGLE_OAUTH_CLIENT_SECRET;
|
|
||||||
if (!clientId || !clientSecret) {
|
|
||||||
throw new Error('Missing Google OAuth client credentials');
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
|
||||||
client_id: clientId,
|
|
||||||
client_secret: clientSecret,
|
|
||||||
refresh_token: integration.refreshToken,
|
|
||||||
grant_type: 'refresh_token'
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await fetch('https://oauth2.googleapis.com/token', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
||||||
body: params.toString()
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const text = await response.text();
|
|
||||||
throw new Error(`Google token refresh failed: ${response.status} ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = (await response.json()) as {
|
|
||||||
access_token: string;
|
|
||||||
expires_in?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const expiresAt = data.expires_in
|
|
||||||
? new Date(Date.now() + data.expires_in * 1000).toISOString()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
await repo.updateTokens(integration._id, {
|
|
||||||
accessToken: data.access_token,
|
|
||||||
accessTokenExpiresAt: expiresAt
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...integration,
|
|
||||||
accessToken: data.access_token,
|
|
||||||
accessTokenExpiresAt: expiresAt
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function refreshDropboxToken(
|
|
||||||
integration: PokedexExportIntegration,
|
|
||||||
repo: PokedexExportIntegrationRepository
|
|
||||||
): Promise<PokedexExportIntegration> {
|
|
||||||
if (!integration.refreshToken) {
|
|
||||||
throw new Error('Missing Dropbox refresh token');
|
|
||||||
}
|
|
||||||
|
|
||||||
const env = getEnv();
|
|
||||||
const clientId = env.DROPBOX_OAUTH_CLIENT_ID;
|
|
||||||
const clientSecret = env.DROPBOX_OAUTH_CLIENT_SECRET;
|
|
||||||
if (!clientId || !clientSecret) {
|
|
||||||
throw new Error('Missing Dropbox OAuth client credentials');
|
|
||||||
}
|
|
||||||
|
|
||||||
const params = new URLSearchParams({
|
|
||||||
client_id: clientId,
|
|
||||||
client_secret: clientSecret,
|
|
||||||
refresh_token: integration.refreshToken,
|
|
||||||
grant_type: 'refresh_token'
|
|
||||||
});
|
|
||||||
|
|
||||||
const response = await fetch('https://api.dropbox.com/oauth2/token', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
||||||
body: params.toString()
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const text = await response.text();
|
|
||||||
throw new Error(`Dropbox token refresh failed: ${response.status} ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = (await response.json()) as {
|
|
||||||
access_token: string;
|
|
||||||
expires_in?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
const expiresAt = data.expires_in
|
|
||||||
? new Date(Date.now() + data.expires_in * 1000).toISOString()
|
|
||||||
: null;
|
|
||||||
|
|
||||||
await repo.updateTokens(integration._id, {
|
|
||||||
accessToken: data.access_token,
|
|
||||||
accessTokenExpiresAt: expiresAt
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
...integration,
|
|
||||||
accessToken: data.access_token,
|
|
||||||
accessTokenExpiresAt: expiresAt
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function ensureAccessToken(
|
|
||||||
integration: PokedexExportIntegration,
|
|
||||||
repo: PokedexExportIntegrationRepository
|
|
||||||
): Promise<PokedexExportIntegration> {
|
|
||||||
if (!shouldRefreshToken(integration.accessTokenExpiresAt)) {
|
|
||||||
return integration;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (integration.provider === 'google_drive') {
|
|
||||||
return await refreshGoogleToken(integration, repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (integration.provider === 'dropbox') {
|
|
||||||
return await refreshDropboxToken(integration, repo);
|
|
||||||
}
|
|
||||||
|
|
||||||
return integration;
|
|
||||||
}
|
|
||||||
|
|
||||||
type GoogleDriveMetadata = {
|
|
||||||
files?: Record<string, string>;
|
|
||||||
};
|
|
||||||
|
|
||||||
function getGoogleFileId(metadata: Record<string, unknown> | null, pokedexId: string): string | null {
|
|
||||||
const data = metadata as GoogleDriveMetadata | null;
|
|
||||||
const fileId = data?.files?.[pokedexId];
|
|
||||||
return typeof fileId === 'string' && fileId ? fileId : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function withGoogleFileId(
|
|
||||||
metadata: Record<string, unknown> | null,
|
|
||||||
pokedexId: string,
|
|
||||||
fileId: string
|
|
||||||
): Record<string, unknown> {
|
|
||||||
const data = (metadata as GoogleDriveMetadata | null) ?? {};
|
|
||||||
const files = { ...(data.files ?? {}) };
|
|
||||||
files[pokedexId] = fileId;
|
|
||||||
return { ...data, files };
|
|
||||||
}
|
|
||||||
|
|
||||||
function withoutGoogleFileId(
|
|
||||||
metadata: Record<string, unknown> | null,
|
|
||||||
pokedexId: string
|
|
||||||
): Record<string, unknown> | null {
|
|
||||||
const data = (metadata as GoogleDriveMetadata | null) ?? {};
|
|
||||||
if (!data.files || !data.files[pokedexId]) return metadata;
|
|
||||||
const files = { ...data.files };
|
|
||||||
delete files[pokedexId];
|
|
||||||
const next = { ...data, files };
|
|
||||||
if (Object.keys(files).length === 0) {
|
|
||||||
delete (next as GoogleDriveMetadata).files;
|
|
||||||
}
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function uploadToGoogleDrive(
|
|
||||||
integration: PokedexExportIntegration,
|
|
||||||
repo: PokedexExportIntegrationRepository,
|
|
||||||
pokedex: Pokedex,
|
|
||||||
csv: string
|
|
||||||
): Promise<void> {
|
|
||||||
const refreshed = await ensureAccessToken(integration, repo);
|
|
||||||
const fileName = sanitizeFileName(pokedex.name, 'pokedex.csv');
|
|
||||||
|
|
||||||
let folderId = refreshed.folderId?.trim() ?? '';
|
|
||||||
if (!folderId) {
|
|
||||||
try {
|
|
||||||
const folderResponse = await fetch(
|
|
||||||
'https://www.googleapis.com/drive/v3/files?' +
|
|
||||||
new URLSearchParams({
|
|
||||||
q: "name='Living Dex Tracker' and mimeType='application/vnd.google-apps.folder' and trashed=false",
|
|
||||||
fields: 'files(id,name)',
|
|
||||||
pageSize: '1'
|
|
||||||
}).toString(),
|
|
||||||
{
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${refreshed.accessToken}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (folderResponse.ok) {
|
|
||||||
const folderData = (await folderResponse.json()) as { files?: Array<{ id: string }> };
|
|
||||||
folderId = folderData.files?.[0]?.id ?? '';
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Failed to lookup Google Drive folder, using root:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!folderId) {
|
|
||||||
try {
|
|
||||||
const createResponse = await fetch('https://www.googleapis.com/drive/v3/files', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${refreshed.accessToken}`,
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
name: 'Living Dex Tracker',
|
|
||||||
mimeType: 'application/vnd.google-apps.folder'
|
|
||||||
})
|
|
||||||
});
|
|
||||||
if (createResponse.ok) {
|
|
||||||
const created = (await createResponse.json()) as { id?: string };
|
|
||||||
folderId = created.id ?? '';
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.warn('Failed to create Google Drive folder, using root:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingFileId = getGoogleFileId(refreshed.metadata, pokedex._id);
|
|
||||||
let currentFileId = existingFileId;
|
|
||||||
|
|
||||||
for (let attempt = 0; attempt < 2; attempt++) {
|
|
||||||
const metadata: Record<string, unknown> = {
|
|
||||||
name: fileName,
|
|
||||||
mimeType: 'text/csv'
|
|
||||||
};
|
|
||||||
if (folderId && !currentFileId) {
|
|
||||||
metadata.parents = [folderId];
|
|
||||||
}
|
|
||||||
|
|
||||||
const boundary = `boundary_${randomUUID()}`;
|
|
||||||
const body = [
|
|
||||||
`--${boundary}`,
|
|
||||||
'Content-Type: application/json; charset=UTF-8',
|
|
||||||
'',
|
|
||||||
JSON.stringify(metadata),
|
|
||||||
`--${boundary}`,
|
|
||||||
'Content-Type: text/csv',
|
|
||||||
'',
|
|
||||||
csv,
|
|
||||||
`--${boundary}--`
|
|
||||||
].join('\r\n');
|
|
||||||
|
|
||||||
const url = currentFileId
|
|
||||||
? `https://www.googleapis.com/upload/drive/v3/files/${currentFileId}?uploadType=multipart`
|
|
||||||
: 'https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart';
|
|
||||||
const method = currentFileId ? 'PATCH' : 'POST';
|
|
||||||
const uploadUrl = currentFileId && folderId
|
|
||||||
? `${url}&addParents=${encodeURIComponent(folderId)}`
|
|
||||||
: url;
|
|
||||||
|
|
||||||
const response = await fetch(uploadUrl, {
|
|
||||||
method,
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${refreshed.accessToken}`,
|
|
||||||
'Content-Type': `multipart/related; boundary=${boundary}`
|
|
||||||
},
|
|
||||||
body
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const text = await response.text();
|
|
||||||
if (currentFileId && response.status === 404 && attempt === 0) {
|
|
||||||
const nextMetadata = withoutGoogleFileId(refreshed.metadata, pokedex._id);
|
|
||||||
await repo.updateExportStatus(refreshed._id, { metadata: nextMetadata });
|
|
||||||
currentFileId = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
throw new Error(`Google Drive upload failed: ${response.status} ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = (await response.json()) as { id?: string };
|
|
||||||
if (data.id && folderId) {
|
|
||||||
await repo.updateExportStatus(refreshed._id, {
|
|
||||||
folderId
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentFileId && data.id) {
|
|
||||||
const nextMetadata = withGoogleFileId(refreshed.metadata, pokedex._id, data.id);
|
|
||||||
await repo.updateExportStatus(refreshed._id, { metadata: nextMetadata });
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function uploadToDropbox(
|
|
||||||
integration: PokedexExportIntegration,
|
|
||||||
repo: PokedexExportIntegrationRepository,
|
|
||||||
pokedex: Pokedex,
|
|
||||||
csv: string
|
|
||||||
): Promise<void> {
|
|
||||||
const refreshed = await ensureAccessToken(integration, repo);
|
|
||||||
const fileName = sanitizeFileName(pokedex.name, 'pokedex.csv');
|
|
||||||
const trimmedPath = refreshed.path?.trim() ?? '';
|
|
||||||
let targetPath = trimmedPath;
|
|
||||||
if (!targetPath) {
|
|
||||||
targetPath = `/${fileName}`;
|
|
||||||
} else if (targetPath.endsWith('/')) {
|
|
||||||
targetPath = `${targetPath}${fileName}`;
|
|
||||||
} else if (!targetPath.toLowerCase().endsWith('.csv')) {
|
|
||||||
targetPath = `${targetPath}/${fileName}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch('https://content.dropboxapi.com/2/files/upload', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${refreshed.accessToken}`,
|
|
||||||
'Content-Type': 'application/octet-stream',
|
|
||||||
'Dropbox-API-Arg': JSON.stringify({
|
|
||||||
path: targetPath,
|
|
||||||
mode: 'overwrite',
|
|
||||||
mute: true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
body: csv
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const text = await response.text();
|
|
||||||
throw new Error(`Dropbox upload failed: ${response.status} ${text}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function exportToIntegration(
|
|
||||||
integration: PokedexExportIntegration,
|
|
||||||
repo: PokedexExportIntegrationRepository,
|
|
||||||
pokedex: Pokedex,
|
|
||||||
csv: string
|
|
||||||
): Promise<void> {
|
|
||||||
if (integration.provider === 'google_drive') {
|
|
||||||
await uploadToGoogleDrive(integration, repo, pokedex, csv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (integration.provider === 'dropbox') {
|
|
||||||
await uploadToDropbox(integration, repo, pokedex, csv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function exportPokedexIfConfigured(
|
|
||||||
supabase: SupabaseClient,
|
|
||||||
userId: string,
|
|
||||||
pokedexId: string
|
|
||||||
): Promise<PokedexExportResult> {
|
|
||||||
const pokedexRepo = new PokedexRepository(supabase, userId);
|
|
||||||
const pokedex = await pokedexRepo.findById(pokedexId);
|
|
||||||
if (!pokedex) {
|
|
||||||
return { attempted: 0, succeeded: 0, failed: [] };
|
|
||||||
}
|
|
||||||
|
|
||||||
const integrationRepo = new PokedexExportIntegrationRepository(supabase, userId, pokedexId);
|
|
||||||
const integrations = await integrationRepo.listEnabledForPokedexOrUser();
|
|
||||||
if (integrations.length === 0) {
|
|
||||||
return { attempted: 0, succeeded: 0, failed: [] };
|
|
||||||
}
|
|
||||||
|
|
||||||
const dexScopes = await resolveDexScopes(supabase, pokedex);
|
|
||||||
const combinedRepo = new CombinedDataRepository(supabase, userId, pokedexId);
|
|
||||||
const combinedData = await combinedRepo.findAllCombinedData(
|
|
||||||
userId,
|
|
||||||
!!pokedex.isFormDex,
|
|
||||||
'',
|
|
||||||
pokedex.gameScope || '',
|
|
||||||
dexScopes
|
|
||||||
);
|
|
||||||
const csv = buildCsv(pokedex, combinedData);
|
|
||||||
|
|
||||||
const failures: ExportFailure[] = [];
|
|
||||||
let successes = 0;
|
|
||||||
|
|
||||||
for (const integration of integrations) {
|
|
||||||
const scopedRepo = new PokedexExportIntegrationRepository(
|
|
||||||
supabase,
|
|
||||||
userId,
|
|
||||||
integration.pokedexId ?? null
|
|
||||||
);
|
|
||||||
try {
|
|
||||||
await exportToIntegration(integration, scopedRepo, pokedex, csv);
|
|
||||||
await scopedRepo.updateExportStatus(integration._id, {
|
|
||||||
lastExportedAt: new Date().toISOString(),
|
|
||||||
lastError: null
|
|
||||||
});
|
|
||||||
successes++;
|
|
||||||
} catch (error) {
|
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
|
||||||
failures.push({
|
|
||||||
integrationId: integration._id,
|
|
||||||
provider: integration.provider,
|
|
||||||
error: message
|
|
||||||
});
|
|
||||||
await scopedRepo.updateExportStatus(integration._id, {
|
|
||||||
lastError: message
|
|
||||||
});
|
|
||||||
console.error('Failed to export pokedex:', integration.provider, message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
attempted: integrations.length,
|
|
||||||
succeeded: successes,
|
|
||||||
failed: failures
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
import type { Pokedex } from '$lib/models/Pokedex';
|
|
||||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
|
||||||
import { resolveDexScopes } from '$lib/services/PokedexDexScopeService';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate expected pokedex entries based on pokedex configuration
|
|
||||||
* Applies the same filtering logic as CombinedDataRepository
|
|
||||||
* @throws Error if the Supabase query fails
|
|
||||||
*/
|
|
||||||
export async function calculateExpectedEntries(
|
|
||||||
supabase: SupabaseClient,
|
|
||||||
pokedex: Pokedex
|
|
||||||
): Promise<number[]> {
|
|
||||||
const dexScopes = await resolveDexScopes(supabase, pokedex);
|
|
||||||
|
|
||||||
if (dexScopes.length > 0) {
|
|
||||||
const { data: dexEntries, error: dexError } = await supabase
|
|
||||||
.from('game_pokedex_entries')
|
|
||||||
.select('pokemonId')
|
|
||||||
.in('dexId', dexScopes);
|
|
||||||
|
|
||||||
if (dexError) {
|
|
||||||
console.error('Error calculating dex-scoped entries:', dexError);
|
|
||||||
throw new Error(`Failed to calculate dex-scoped entries: ${dexError.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const uniqueIds = Array.from(new Set(dexEntries?.map((row) => row.pokemonId) || []));
|
|
||||||
if (uniqueIds.length === 0) return [];
|
|
||||||
|
|
||||||
if (!pokedex.isFormDex) {
|
|
||||||
const { data: entries, error: entryError } = await supabase
|
|
||||||
.from('pokedex_entries')
|
|
||||||
.select('id, pokemon, form')
|
|
||||||
.in('id', uniqueIds);
|
|
||||||
|
|
||||||
if (entryError) {
|
|
||||||
console.error('Error filtering base forms for dex scopes:', entryError);
|
|
||||||
throw new Error(`Failed to filter base forms: ${entryError.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
entries
|
|
||||||
?.filter(
|
|
||||||
(entry) =>
|
|
||||||
entry.form === null ||
|
|
||||||
entry.form === 'male' ||
|
|
||||||
(entry.pokemon === 'Unown' && entry.form === 'A')
|
|
||||||
)
|
|
||||||
.map((entry) => entry.id) || []
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return uniqueIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
let query = supabase.from('pokedex_entries').select('id');
|
|
||||||
|
|
||||||
// Apply form filter: if isFormDex is false, only include base forms
|
|
||||||
// Base forms have form IS NULL, except Unown which has no base form (use 'A')
|
|
||||||
if (!pokedex.isFormDex) {
|
|
||||||
query = query.or('form.is.null,form.eq.male,and(pokemon.eq.Unown,form.eq.A)');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply region filter: if gameScope is specified, filter by region
|
|
||||||
if (pokedex.gameScope) {
|
|
||||||
// Determine region from gameScope using games table.
|
|
||||||
// We keep games.region as a denormalized convenience column.
|
|
||||||
const { data: regionData, error: regionError } = await supabase
|
|
||||||
.from('games')
|
|
||||||
.select('region')
|
|
||||||
.eq('displayName', pokedex.gameScope)
|
|
||||||
.maybeSingle();
|
|
||||||
|
|
||||||
if (regionError) {
|
|
||||||
console.error('Error looking up region for gameScope:', pokedex.gameScope, regionError);
|
|
||||||
throw new Error(
|
|
||||||
`Failed to lookup region for gameScope "${pokedex.gameScope}": ${regionError.message}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (regionData?.region) {
|
|
||||||
query = query.eq('regionToCatchIn', regionData.region);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply game filter: if gameScope is specified, filter by gamesToCatchIn array
|
|
||||||
if (pokedex.gameScope) {
|
|
||||||
query = query.contains('gamesToCatchIn', [pokedex.gameScope]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data, error } = await query;
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error calculating expected entries:', error);
|
|
||||||
throw new Error(`Failed to calculate expected entries: ${error.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data?.map((entry) => entry.id) || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populate pokedex_entries_mapping table for a pokedex
|
|
||||||
* Uses chunked upsert to avoid UNIQUE constraint violations and request size limits
|
|
||||||
* @throws Error if the Supabase upsert fails
|
|
||||||
*/
|
|
||||||
export async function populatePokedexMappings(
|
|
||||||
supabase: SupabaseClient,
|
|
||||||
pokedexId: string,
|
|
||||||
pokedex: Pokedex
|
|
||||||
): Promise<void> {
|
|
||||||
const expectedEntryIds = await calculateExpectedEntries(supabase, pokedex);
|
|
||||||
|
|
||||||
if (expectedEntryIds.length === 0) {
|
|
||||||
console.warn(`No expected entries calculated for pokedex ${pokedexId}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// New schema writes to pokedex_pokemon_mapping; column is pokemonId
|
|
||||||
const mappings = expectedEntryIds.map((pokemonId) => ({
|
|
||||||
pokedexId,
|
|
||||||
pokemonId
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Process in chunks to avoid request size limits
|
|
||||||
const CHUNK_SIZE = 500;
|
|
||||||
for (let i = 0; i < mappings.length; i += CHUNK_SIZE) {
|
|
||||||
const chunk = mappings.slice(i, i + CHUNK_SIZE);
|
|
||||||
const { error } = await supabase.from('pokedex_pokemon_mapping').upsert(chunk, {
|
|
||||||
onConflict: 'pokedexId,pokemonId',
|
|
||||||
ignoreDuplicates: true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error populating pokedex mappings:', error);
|
|
||||||
throw new Error(`Failed to populate pokedex mappings: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Recalculate pokedex_entries_mapping table for a pokedex (used on update)
|
|
||||||
* Uses a single atomic RPC call to prevent orphaned pokedexes
|
|
||||||
* @throws Error if the Supabase RPC call fails
|
|
||||||
*/
|
|
||||||
export async function recalculatePokedexMappings(
|
|
||||||
supabase: SupabaseClient,
|
|
||||||
pokedexId: string,
|
|
||||||
pokedex: Pokedex
|
|
||||||
): Promise<void> {
|
|
||||||
const expectedEntryIds = await calculateExpectedEntries(supabase, pokedex);
|
|
||||||
|
|
||||||
if (expectedEntryIds.length === 0) {
|
|
||||||
console.warn(`No expected entries calculated for pokedex ${pokedexId}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Call the atomic RPC function to delete old mappings and insert new ones
|
|
||||||
const { error } = await supabase.rpc('recalculate_pokedex_mappings', {
|
|
||||||
p_pokedex_id: pokedexId,
|
|
||||||
p_entry_ids: expectedEntryIds
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error recalculating pokedex mappings:', error);
|
|
||||||
throw new Error(`Failed to recalculate pokedex mappings: ${error.message}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
import { writable } from 'svelte/store';
|
|
||||||
|
|
||||||
type Theme = 'pokeball' | 'dark';
|
|
||||||
|
|
||||||
const STORAGE_KEY = 'theme';
|
|
||||||
|
|
||||||
function isTheme(type: string): type is Theme {
|
|
||||||
return type === 'pokeball' || type === 'dark';
|
|
||||||
}
|
|
||||||
|
|
||||||
function createThemeStore() {
|
|
||||||
// Get stored theme from localStorage or default to 'pokeball'
|
|
||||||
let initialTheme: Theme = 'pokeball';
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
try {
|
|
||||||
const storedTheme = localStorage.getItem(STORAGE_KEY);
|
|
||||||
if (storedTheme && isTheme(storedTheme)) {
|
|
||||||
initialTheme = storedTheme;
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// ignore (privacy mode / disabled storage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const { subscribe, set: writableSet, update } = writable<Theme>(initialTheme);
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe,
|
|
||||||
set: (value: Theme) => {
|
|
||||||
if (isTheme(value)) {
|
|
||||||
writableSet(value);
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
try {
|
|
||||||
localStorage.setItem(STORAGE_KEY, value);
|
|
||||||
} catch {
|
|
||||||
// ignore (privacy mode / disabled storage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toggle: () => {
|
|
||||||
update((theme) => {
|
|
||||||
const newTheme = theme === 'pokeball' ? 'dark' : 'pokeball';
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
try {
|
|
||||||
localStorage.setItem(STORAGE_KEY, newTheme);
|
|
||||||
} catch {
|
|
||||||
// ignore (privacy mode / disabled storage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newTheme;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
init: () => {
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
try {
|
|
||||||
const stored = localStorage.getItem(STORAGE_KEY);
|
|
||||||
if (stored && isTheme(stored)) {
|
|
||||||
writableSet(stored);
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// ignore (privacy mode / disabled storage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export const theme = createThemeStore();
|
|
||||||
|
|
||||||
// Helper function to apply theme to HTML element
|
|
||||||
export function applyTheme(themeValue: Theme) {
|
|
||||||
if (typeof document !== 'undefined') {
|
|
||||||
document.documentElement.setAttribute('data-theme', themeValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import type { RequestEvent } from '@sveltejs/kit';
|
|
||||||
import { error } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the user session and returns the authenticated user ID
|
|
||||||
* Throws a 401 error if the user is not authenticated
|
|
||||||
*/
|
|
||||||
export async function requireAuth(event: RequestEvent): Promise<string> {
|
|
||||||
const { session, user } = await event.locals.safeGetSession();
|
|
||||||
|
|
||||||
if (!session || !user) {
|
|
||||||
throw error(401, 'Authentication required');
|
|
||||||
}
|
|
||||||
|
|
||||||
return user.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Optionally validates the user session and returns the user ID if authenticated
|
|
||||||
* Returns null if not authenticated (no error thrown)
|
|
||||||
*/
|
|
||||||
export async function getOptionalUserId(event: RequestEvent): Promise<string | null> {
|
|
||||||
try {
|
|
||||||
const { session, user } = await event.locals.safeGetSession();
|
|
||||||
return user?.id || null;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
/**
|
|
||||||
* Calculate box placement for Pokémon based on their position in a sorted list
|
|
||||||
*
|
|
||||||
* Box layout: 6 columns × 5 rows = 30 Pokémon per box
|
|
||||||
*
|
|
||||||
* @param index - Zero-based index in the sorted list
|
|
||||||
* @returns Box placement with box number, row, and column (1-indexed)
|
|
||||||
*/
|
|
||||||
export function calculateBoxPlacement(index: number): {
|
|
||||||
box: number;
|
|
||||||
row: number;
|
|
||||||
column: number;
|
|
||||||
} {
|
|
||||||
const POKEMON_PER_BOX = 30;
|
|
||||||
const COLUMNS_PER_BOX = 6;
|
|
||||||
const ROWS_PER_BOX = 5;
|
|
||||||
|
|
||||||
// Calculate which box this Pokémon belongs to (1-indexed)
|
|
||||||
const box = Math.floor(index / POKEMON_PER_BOX) + 1;
|
|
||||||
|
|
||||||
// Calculate position within the box (0-indexed)
|
|
||||||
const positionInBox = index % POKEMON_PER_BOX;
|
|
||||||
|
|
||||||
// Calculate row and column (1-indexed)
|
|
||||||
const row = Math.floor(positionInBox / COLUMNS_PER_BOX) + 1;
|
|
||||||
const column = (positionInBox % COLUMNS_PER_BOX) + 1;
|
|
||||||
|
|
||||||
return { box, row, column };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate all unique box numbers needed for a list of Pokémon
|
|
||||||
*
|
|
||||||
* @param count - Total number of Pokémon
|
|
||||||
* @returns Array of box numbers (1-indexed)
|
|
||||||
*/
|
|
||||||
export function calculateBoxNumbers(count: number): number[] {
|
|
||||||
const POKEMON_PER_BOX = 30;
|
|
||||||
const totalBoxes = Math.ceil(count / POKEMON_PER_BOX);
|
|
||||||
return Array.from({ length: totalBoxes }, (_, i) => i + 1);
|
|
||||||
}
|
|
||||||
@@ -1,260 +0,0 @@
|
|||||||
import { writable, type Readable } from 'svelte/store';
|
|
||||||
import type { CatchRecord } from '$lib/models/CatchRecord';
|
|
||||||
|
|
||||||
export type CatchRecordWriteQueueStatus = {
|
|
||||||
pending: number;
|
|
||||||
inFlight: number;
|
|
||||||
lastError: string | null;
|
|
||||||
lastFlushAttemptAt: number | null;
|
|
||||||
lastSuccessfulFlushAt: number | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
type QueueItem = {
|
|
||||||
record: CatchRecord;
|
|
||||||
attempts: number;
|
|
||||||
notBefore: number; // unix ms
|
|
||||||
debounceTimer: ReturnType<typeof setTimeout> | null;
|
|
||||||
version: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CreateCatchRecordWriteQueueOptions = {
|
|
||||||
/**
|
|
||||||
* URL to the pokédex-scoped catch-records endpoint.
|
|
||||||
* Example: `/api/pokedexes/${pokedexId}/catch-records`
|
|
||||||
*/
|
|
||||||
endpointUrl: string;
|
|
||||||
/**
|
|
||||||
* Fetch implementation to use (usually the `fetch` provided by SvelteKit load).
|
|
||||||
*/
|
|
||||||
fetchFn: typeof fetch;
|
|
||||||
/** Max number of records sent per request. */
|
|
||||||
batchSize?: number;
|
|
||||||
/** Max number of concurrent in-flight requests. */
|
|
||||||
concurrency?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type EnqueueCatchRecordWriteOptions = {
|
|
||||||
/** Debounce before the record becomes eligible for flushing (ms). */
|
|
||||||
debounceMs?: number;
|
|
||||||
/** If true, schedule an immediate flush attempt after enqueue. */
|
|
||||||
flushSoon?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type FlushOptions = {
|
|
||||||
/**
|
|
||||||
* Use `keepalive` to improve best-effort delivery during `pagehide`.
|
|
||||||
* Note: browsers impose body-size limits on keepalive requests.
|
|
||||||
*/
|
|
||||||
keepalive?: boolean;
|
|
||||||
/**
|
|
||||||
* Limit number of items flushed in this attempt.
|
|
||||||
* Useful for keepalive flushes on tab close.
|
|
||||||
*/
|
|
||||||
limit?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
function keyFor(record: CatchRecord): string {
|
|
||||||
return `${record.userId}:${record.pokedexId}:${record.pokemonId}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function backoffMs(attempts: number): number {
|
|
||||||
// Exponential backoff with jitter: 250ms, 500ms, 1s, 2s, 4s... capped.
|
|
||||||
const base = 250 * Math.pow(2, Math.max(0, attempts - 1));
|
|
||||||
const capped = Math.min(base, 10_000);
|
|
||||||
const jitter = Math.floor(Math.random() * 200);
|
|
||||||
return capped + jitter;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createCatchRecordWriteQueue(options: CreateCatchRecordWriteQueueOptions): {
|
|
||||||
enqueue: (record: CatchRecord, opts?: EnqueueCatchRecordWriteOptions) => void;
|
|
||||||
flushNow: (opts?: FlushOptions) => Promise<void>;
|
|
||||||
getStatus: Readable<CatchRecordWriteQueueStatus>;
|
|
||||||
getPendingCount: () => number;
|
|
||||||
clearError: () => void;
|
|
||||||
} {
|
|
||||||
const { endpointUrl, fetchFn, batchSize = 100, concurrency = 1 } = options;
|
|
||||||
|
|
||||||
const items = new Map<string, QueueItem>();
|
|
||||||
let scheduled: ReturnType<typeof setTimeout> | null = null;
|
|
||||||
let inFlight = 0;
|
|
||||||
|
|
||||||
const statusStore = writable<CatchRecordWriteQueueStatus>({
|
|
||||||
pending: 0,
|
|
||||||
inFlight: 0,
|
|
||||||
lastError: null,
|
|
||||||
lastFlushAttemptAt: null,
|
|
||||||
lastSuccessfulFlushAt: null
|
|
||||||
});
|
|
||||||
|
|
||||||
function updateStatus(patch: Partial<CatchRecordWriteQueueStatus>) {
|
|
||||||
statusStore.update((s) => ({
|
|
||||||
...s,
|
|
||||||
pending: items.size,
|
|
||||||
inFlight,
|
|
||||||
...patch
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function computeNextWakeup(): number | null {
|
|
||||||
let next: number | null = null;
|
|
||||||
const now = Date.now();
|
|
||||||
for (const [, item] of items) {
|
|
||||||
if (item.debounceTimer) continue;
|
|
||||||
if (item.notBefore <= now) {
|
|
||||||
return now;
|
|
||||||
}
|
|
||||||
next = next === null ? item.notBefore : Math.min(next, item.notBefore);
|
|
||||||
}
|
|
||||||
return next;
|
|
||||||
}
|
|
||||||
|
|
||||||
function scheduleFlush() {
|
|
||||||
if (scheduled) return;
|
|
||||||
const next = computeNextWakeup();
|
|
||||||
if (next === null) return;
|
|
||||||
const delay = Math.max(0, next - Date.now());
|
|
||||||
scheduled = setTimeout(async () => {
|
|
||||||
scheduled = null;
|
|
||||||
await flushNow();
|
|
||||||
}, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function flushBatch(opts?: FlushOptions): Promise<void> {
|
|
||||||
if (typeof navigator !== 'undefined' && navigator.onLine === false) {
|
|
||||||
// Stay queued; caller can retry when online.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (inFlight >= concurrency) return;
|
|
||||||
|
|
||||||
const now = Date.now();
|
|
||||||
const eligible: Array<[string, QueueItem]> = [];
|
|
||||||
for (const entry of items.entries()) {
|
|
||||||
const [k, item] = entry;
|
|
||||||
if (item.debounceTimer) continue;
|
|
||||||
if (item.notBefore > now) continue;
|
|
||||||
eligible.push([k, item]);
|
|
||||||
if (eligible.length >= (opts?.limit ?? batchSize)) break;
|
|
||||||
}
|
|
||||||
if (eligible.length === 0) return;
|
|
||||||
|
|
||||||
inFlight++;
|
|
||||||
updateStatus({ lastFlushAttemptAt: now });
|
|
||||||
try {
|
|
||||||
const payload = eligible.map(([, item]) => item.record);
|
|
||||||
const response = await fetchFn(endpointUrl, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
// keepalive improves odds during `pagehide`.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
keepalive: !!opts?.keepalive,
|
|
||||||
credentials: 'include'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) {
|
|
||||||
const text = await response.text();
|
|
||||||
throw new Error(`Failed to flush catch records: ${response.status} ${text}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Success: drop the flushed keys.
|
|
||||||
for (const [k, sentItem] of eligible) {
|
|
||||||
const current = items.get(k);
|
|
||||||
if (!current) {
|
|
||||||
items.delete(k);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Only clear if nothing newer was enqueued after this batch started.
|
|
||||||
if (current.version === sentItem.version) {
|
|
||||||
items.delete(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updateStatus({ lastError: null, lastSuccessfulFlushAt: Date.now() });
|
|
||||||
} catch (e) {
|
|
||||||
const message = e instanceof Error ? e.message : String(e);
|
|
||||||
// Backoff all eligible items and keep them.
|
|
||||||
for (const [k, item] of eligible) {
|
|
||||||
const current = items.get(k);
|
|
||||||
if (!current) continue;
|
|
||||||
if (current.version !== item.version) continue;
|
|
||||||
const nextAttempts = item.attempts + 1;
|
|
||||||
items.set(k, {
|
|
||||||
...item,
|
|
||||||
attempts: nextAttempts,
|
|
||||||
notBefore: Date.now() + backoffMs(nextAttempts)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
updateStatus({ lastError: message });
|
|
||||||
} finally {
|
|
||||||
inFlight--;
|
|
||||||
updateStatus({});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function flushNow(opts?: FlushOptions): Promise<void> {
|
|
||||||
updateStatus({});
|
|
||||||
// Drain in waves while eligible work exists and we have capacity.
|
|
||||||
// We intentionally do not block indefinitely; this is a “best-effort background flush”.
|
|
||||||
for (let i = 0; i < 10; i++) {
|
|
||||||
if (items.size === 0) break;
|
|
||||||
await flushBatch(opts);
|
|
||||||
// If nothing is eligible yet, schedule the next wakeup and exit.
|
|
||||||
const next = computeNextWakeup();
|
|
||||||
if (next !== null && next > Date.now()) break;
|
|
||||||
if (inFlight >= concurrency) break;
|
|
||||||
}
|
|
||||||
scheduleFlush();
|
|
||||||
}
|
|
||||||
|
|
||||||
function enqueue(record: CatchRecord, opts?: EnqueueCatchRecordWriteOptions) {
|
|
||||||
const k = keyFor(record);
|
|
||||||
const now = Date.now();
|
|
||||||
const existing = items.get(k);
|
|
||||||
const debounceMs = opts?.debounceMs ?? 0;
|
|
||||||
const nextVersion = (existing?.version ?? 0) + 1;
|
|
||||||
|
|
||||||
// Clear any pending debounce timer: latest state always wins.
|
|
||||||
if (existing?.debounceTimer) {
|
|
||||||
clearTimeout(existing.debounceTimer);
|
|
||||||
}
|
|
||||||
|
|
||||||
let debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
||||||
let notBefore = now;
|
|
||||||
if (debounceMs > 0) {
|
|
||||||
notBefore = now + debounceMs;
|
|
||||||
debounceTimer = setTimeout(() => {
|
|
||||||
const item = items.get(k);
|
|
||||||
if (!item) return;
|
|
||||||
items.set(k, { ...item, debounceTimer: null, notBefore: Date.now() });
|
|
||||||
updateStatus({});
|
|
||||||
scheduleFlush();
|
|
||||||
}, debounceMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
items.set(k, {
|
|
||||||
record,
|
|
||||||
attempts: existing?.attempts ?? 0,
|
|
||||||
notBefore,
|
|
||||||
debounceTimer,
|
|
||||||
version: nextVersion
|
|
||||||
});
|
|
||||||
updateStatus({});
|
|
||||||
if (opts?.flushSoon !== false) scheduleFlush();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPendingCount(): number {
|
|
||||||
return items.size;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clearError() {
|
|
||||||
updateStatus({ lastError: null });
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
enqueue,
|
|
||||||
flushNow,
|
|
||||||
getStatus: { subscribe: statusStore.subscribe },
|
|
||||||
getPendingCount,
|
|
||||||
clearError
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import mongoose from 'mongoose';
|
||||||
|
import { getEnv } from '$lib/utils/env';
|
||||||
|
const env = getEnv();
|
||||||
|
|
||||||
|
/*
|
||||||
|
0 - disconnected
|
||||||
|
1 - connected
|
||||||
|
2 - connecting
|
||||||
|
3 - disconnecting
|
||||||
|
4 - uninitialized
|
||||||
|
*/
|
||||||
|
let mongoConnectionState = 0;
|
||||||
|
|
||||||
|
export const dbConnect = async () => {
|
||||||
|
if (mongoConnectionState === 1) {
|
||||||
|
console.log('Connection already established');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mongoose.connections.length > 0) {
|
||||||
|
mongoConnectionState = mongoose.connections[0].readyState;
|
||||||
|
if (mongoConnectionState === 1) {
|
||||||
|
console.log('Using existing connection');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mongoose.connect(env.MONGO_URL, {
|
||||||
|
serverApi: { version: '1', strict: true, deprecationErrors: true }
|
||||||
|
});
|
||||||
|
await mongoose.connection.db.admin().command({ ping: 1 });
|
||||||
|
console.log('Pinged your deployment. You successfully connected to MongoDB!');
|
||||||
|
mongoConnectionState = 1;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error connecting to MongoDB:', error);
|
||||||
|
mongoConnectionState = 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const dbDisconnect = async () => {
|
||||||
|
if (process.env.NODE_ENV === 'development') return;
|
||||||
|
if (mongoConnectionState === 0) return;
|
||||||
|
|
||||||
|
await mongoose.disconnect();
|
||||||
|
mongoConnectionState = 0;
|
||||||
|
console.log('disconnected from mongodb');
|
||||||
|
};
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import { env } from '$env/dynamic/private';
|
|
||||||
|
|
||||||
export function getEnv() {
|
export function getEnv() {
|
||||||
return env;
|
return process.env.hasOwnProperty('MONGO_URL')
|
||||||
|
? process.env
|
||||||
|
: {
|
||||||
|
MONGO_URL: import.meta.env.VITE_MONGO_URL
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
import { randomUUID } from 'node:crypto';
|
|
||||||
import type { RequestEvent } from '@sveltejs/kit';
|
|
||||||
|
|
||||||
export type OAuthStatePayload = {
|
|
||||||
state: string;
|
|
||||||
userId: string;
|
|
||||||
pokedexId?: string | null;
|
|
||||||
provider: string;
|
|
||||||
fileName?: string | null;
|
|
||||||
folderId?: string | null;
|
|
||||||
path?: string | null;
|
|
||||||
returnTo?: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const STATE_MAX_AGE = 10 * 60; // 10 minutes
|
|
||||||
|
|
||||||
export function createOAuthState(): string {
|
|
||||||
return randomUUID();
|
|
||||||
}
|
|
||||||
|
|
||||||
function cookieName(provider: string): string {
|
|
||||||
return `oauth_state_${provider}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function setOAuthStateCookie(
|
|
||||||
event: RequestEvent,
|
|
||||||
provider: string,
|
|
||||||
payload: OAuthStatePayload
|
|
||||||
) {
|
|
||||||
event.cookies.set(cookieName(provider), JSON.stringify(payload), {
|
|
||||||
path: '/',
|
|
||||||
httpOnly: true,
|
|
||||||
sameSite: 'lax',
|
|
||||||
secure: event.url.protocol === 'https:',
|
|
||||||
maxAge: STATE_MAX_AGE
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function readOAuthStateCookie(
|
|
||||||
event: RequestEvent,
|
|
||||||
provider: string
|
|
||||||
): OAuthStatePayload | null {
|
|
||||||
const raw = event.cookies.get(cookieName(provider));
|
|
||||||
if (!raw) return null;
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(raw) as OAuthStatePayload;
|
|
||||||
if (!parsed?.state || !parsed?.userId) return null;
|
|
||||||
return parsed;
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function clearOAuthStateCookie(event: RequestEvent, provider: string) {
|
|
||||||
event.cookies.delete(cookieName(provider), { path: '/' });
|
|
||||||
}
|
|
||||||
@@ -1,141 +0,0 @@
|
|||||||
/**
|
|
||||||
* Maps game names to their corresponding regional Pokédex identifier.
|
|
||||||
* This mapping is used to determine which regional dex number to use when
|
|
||||||
* filtering and ordering Pokémon for a specific game.
|
|
||||||
*/
|
|
||||||
|
|
||||||
type RegionalDexKey =
|
|
||||||
| 'kanto'
|
|
||||||
| 'johto'
|
|
||||||
| 'hoenn'
|
|
||||||
| 'sinnoh'
|
|
||||||
| 'unova_bw'
|
|
||||||
| 'unova_b2w2'
|
|
||||||
| 'kalos_central'
|
|
||||||
| 'kalos_coastal'
|
|
||||||
| 'kalos_mountain'
|
|
||||||
| 'alola_sm'
|
|
||||||
| 'alola_usum'
|
|
||||||
| 'galar'
|
|
||||||
| 'galar_isle_of_armor'
|
|
||||||
| 'galar_crown_tundra'
|
|
||||||
| 'hisui'
|
|
||||||
| 'paldea';
|
|
||||||
|
|
||||||
const gameToRegionalDexMap: Record<string, RegionalDexKey> = {
|
|
||||||
// Kanto region
|
|
||||||
'Red': 'kanto',
|
|
||||||
'Blue': 'kanto',
|
|
||||||
'Yellow': 'kanto',
|
|
||||||
'FireRed': 'kanto',
|
|
||||||
'LeafGreen': 'kanto',
|
|
||||||
'LG: Pikachu': 'kanto',
|
|
||||||
'LG: Eevee': 'kanto',
|
|
||||||
|
|
||||||
// Johto region
|
|
||||||
'Gold': 'johto',
|
|
||||||
'Silver': 'johto',
|
|
||||||
'Crystal': 'johto',
|
|
||||||
'HeartGold': 'johto',
|
|
||||||
'SoulSilver': 'johto',
|
|
||||||
|
|
||||||
// Hoenn region
|
|
||||||
'Ruby': 'hoenn',
|
|
||||||
'Sapphire': 'hoenn',
|
|
||||||
'Emerald': 'hoenn',
|
|
||||||
'OmegaRuby': 'hoenn',
|
|
||||||
'AlphaSapphire': 'hoenn',
|
|
||||||
|
|
||||||
// Sinnoh region
|
|
||||||
'Diamond': 'sinnoh',
|
|
||||||
'Pearl': 'sinnoh',
|
|
||||||
'Platinum': 'sinnoh',
|
|
||||||
'BrilliantDiamond': 'sinnoh',
|
|
||||||
'ShiningPearl': 'sinnoh',
|
|
||||||
|
|
||||||
// Unova region
|
|
||||||
'Black': 'unova_bw',
|
|
||||||
'White': 'unova_bw',
|
|
||||||
'Black2': 'unova_b2w2',
|
|
||||||
'White2': 'unova_b2w2',
|
|
||||||
|
|
||||||
// Kalos region - Note: All XY use all three sub-dexes
|
|
||||||
// We default to Central for simplicity
|
|
||||||
'X': 'kalos_central',
|
|
||||||
'Y': 'kalos_central',
|
|
||||||
|
|
||||||
// Alola region
|
|
||||||
'Sun': 'alola_sm',
|
|
||||||
'Moon': 'alola_sm',
|
|
||||||
'UltraSun': 'alola_usum',
|
|
||||||
'UltraMoon': 'alola_usum',
|
|
||||||
|
|
||||||
// Galar region
|
|
||||||
'Sword': 'galar',
|
|
||||||
'Shield': 'galar',
|
|
||||||
|
|
||||||
// Hisui region
|
|
||||||
'LegendsArceus': 'hisui',
|
|
||||||
|
|
||||||
// Paldea region
|
|
||||||
'Scarlet': 'paldea',
|
|
||||||
'Violet': 'paldea'
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the regional dex key for a given game name.
|
|
||||||
* Returns undefined if the game doesn't have a regional dex mapping.
|
|
||||||
*/
|
|
||||||
export function getRegionalDexKey(gameName: string): RegionalDexKey | undefined {
|
|
||||||
return gameToRegionalDexMap[gameName];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a game has a regional dex mapping.
|
|
||||||
*/
|
|
||||||
export function hasRegionalDex(gameName: string): boolean {
|
|
||||||
return gameName in gameToRegionalDexMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the database column name for a game's regional dex.
|
|
||||||
* Maps game name → database column name (e.g., 'Scarlet' → 'paldea_dex_number').
|
|
||||||
* Returns undefined if the game doesn't have a regional dex mapping.
|
|
||||||
*/
|
|
||||||
export function getRegionalDexColumnName(gameName: string): string | undefined {
|
|
||||||
const regionalKey = getRegionalDexKey(gameName);
|
|
||||||
if (!regionalKey) return undefined;
|
|
||||||
return `${regionalKey}_dex_number`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the frontend field name for a game's regional dex.
|
|
||||||
* Maps game name → PokedexEntry field name (e.g., 'Scarlet' → 'paldeaDexNumber').
|
|
||||||
* Returns undefined if the game doesn't have a regional dex mapping.
|
|
||||||
*/
|
|
||||||
export function getRegionalDexFieldName(gameName: string): string | undefined {
|
|
||||||
const regionalKey = getRegionalDexKey(gameName);
|
|
||||||
if (!regionalKey) return undefined;
|
|
||||||
|
|
||||||
// Map regional key to actual PokedexEntry field name (camelCase)
|
|
||||||
const fieldMap: Record<string, string> = {
|
|
||||||
'kanto': 'kantoDexNumber',
|
|
||||||
'johto': 'johtoDexNumber',
|
|
||||||
'hoenn': 'hoennDexNumber',
|
|
||||||
'sinnoh': 'sinnohDexNumber',
|
|
||||||
'unova_bw': 'unovaBwDexNumber',
|
|
||||||
'unova_b2w2': 'unovaB2w2DexNumber',
|
|
||||||
'kalos_central': 'kalosCentralDexNumber',
|
|
||||||
'kalos_coastal': 'kalosCoastalDexNumber',
|
|
||||||
'kalos_mountain': 'kalosMountainDexNumber',
|
|
||||||
'alola_sm': 'alolaSmDexNumber',
|
|
||||||
'alola_usum': 'alolaUsumDexNumber',
|
|
||||||
'galar': 'galarDexNumber',
|
|
||||||
'galar_isle_of_armor': 'galarIsleOfArmorDexNumber',
|
|
||||||
'galar_crown_tundra': 'galarCrownTundraDexNumber',
|
|
||||||
'hisui': 'hisuiDexNumber',
|
|
||||||
'paldea': 'paldeaDexNumber'
|
|
||||||
};
|
|
||||||
|
|
||||||
return fieldMap[regionalKey];
|
|
||||||
}
|
|
||||||
+2
-24
@@ -8,10 +8,7 @@ import {
|
|||||||
precacheAndRoute,
|
precacheAndRoute,
|
||||||
precache
|
precache
|
||||||
} from 'workbox-precaching';
|
} from 'workbox-precaching';
|
||||||
import { registerRoute } from 'workbox-routing';
|
// import { NavigationRoute, registerRoute } from 'workbox-routing';
|
||||||
import { CacheFirst } from 'workbox-strategies';
|
|
||||||
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
|
|
||||||
import { ExpirationPlugin } from 'workbox-expiration';
|
|
||||||
|
|
||||||
declare let self: ServiceWorkerGlobalScope;
|
declare let self: ServiceWorkerGlobalScope;
|
||||||
|
|
||||||
@@ -23,30 +20,11 @@ self.addEventListener('message', (event) => {
|
|||||||
precache([{ url: '/', revision: null }]);
|
precache([{ url: '/', revision: null }]);
|
||||||
|
|
||||||
// self.__WB_MANIFEST is default injection point
|
// self.__WB_MANIFEST is default injection point
|
||||||
// Handle the case where __WB_MANIFEST might be undefined in development
|
precacheAndRoute(self.__WB_MANIFEST);
|
||||||
const manifest = self.__WB_MANIFEST || [];
|
|
||||||
if (Array.isArray(manifest)) {
|
|
||||||
precacheAndRoute(manifest);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clean old assets
|
// clean old assets
|
||||||
cleanupOutdatedCaches();
|
cleanupOutdatedCaches();
|
||||||
|
|
||||||
registerRoute(
|
|
||||||
({ request }) => request.destination === 'image',
|
|
||||||
new CacheFirst({
|
|
||||||
cacheName: 'image-cache',
|
|
||||||
plugins: [
|
|
||||||
new CacheableResponsePlugin({ statuses: [0, 200] }),
|
|
||||||
new ExpirationPlugin({
|
|
||||||
maxEntries: 3000,
|
|
||||||
maxAgeSeconds: 60 * 60 * 24 * 30,
|
|
||||||
purgeOnQuotaError: true
|
|
||||||
})
|
|
||||||
]
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// let allowlist: undefined | RegExp[];
|
// let allowlist: undefined | RegExp[];
|
||||||
// if (import.meta.env.DEV) allowlist = [/^\/$/];
|
// if (import.meta.env.DEV) allowlist = [/^\/$/];
|
||||||
|
|
||||||
|
|||||||
+25
-32
@@ -5,13 +5,11 @@
|
|||||||
import { type User } from '@supabase/auth-js';
|
import { type User } from '@supabase/auth-js';
|
||||||
import SignIn from '$lib/components/SignIn.svelte';
|
import SignIn from '$lib/components/SignIn.svelte';
|
||||||
import SignOut from '$lib/components/SignOut.svelte';
|
import SignOut from '$lib/components/SignOut.svelte';
|
||||||
import ThemeToggle from '$lib/components/ThemeToggle.svelte';
|
|
||||||
|
|
||||||
import { pwaInfo } from 'virtual:pwa-info';
|
import { pwaInfo } from 'virtual:pwa-info';
|
||||||
import { pwaAssetsHead } from 'virtual:pwa-assets/head';
|
import { pwaAssetsHead } from 'virtual:pwa-assets/head';
|
||||||
|
|
||||||
$: webManifestLink = pwaInfo ? pwaInfo.webManifest.linkTag : '';
|
$: webManifestLink = pwaInfo ? pwaInfo.webManifest.linkTag : '';
|
||||||
const pwaDescription = (pwaAssetsHead as { description?: { content: string } }).description;
|
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
let { supabase } = data;
|
let { supabase } = data;
|
||||||
@@ -23,26 +21,10 @@
|
|||||||
});
|
});
|
||||||
onDestroy(unsubscribe);
|
onDestroy(unsubscribe);
|
||||||
|
|
||||||
let authSubscription: { unsubscribe: () => void } | null = null;
|
onMount(async () => {
|
||||||
|
await getUser();
|
||||||
onMount(() => {
|
|
||||||
void getUser();
|
|
||||||
|
|
||||||
// Listen for auth state changes to keep the user store in sync
|
|
||||||
const {
|
|
||||||
data: { subscription }
|
|
||||||
} = supabase.auth.onAuthStateChange((event, session) => {
|
|
||||||
if (session) {
|
|
||||||
localUser = session.user;
|
|
||||||
} else {
|
|
||||||
localUser = null;
|
|
||||||
}
|
|
||||||
user.set(localUser);
|
|
||||||
});
|
|
||||||
authSubscription = subscription;
|
|
||||||
|
|
||||||
if (pwaInfo) {
|
if (pwaInfo) {
|
||||||
void (async () => {
|
|
||||||
const { registerSW } = await import('virtual:pwa-register');
|
const { registerSW } = await import('virtual:pwa-register');
|
||||||
registerSW({
|
registerSW({
|
||||||
immediate: true,
|
immediate: true,
|
||||||
@@ -58,12 +40,7 @@
|
|||||||
console.log('SW registration error', error);
|
console.log('SW registration error', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
|
||||||
authSubscription?.unsubscribe();
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
async function getUser() {
|
async function getUser() {
|
||||||
@@ -86,8 +63,8 @@
|
|||||||
{#if pwaAssetsHead.themeColor}
|
{#if pwaAssetsHead.themeColor}
|
||||||
<meta name="theme-color" content={pwaAssetsHead.themeColor.content} />
|
<meta name="theme-color" content={pwaAssetsHead.themeColor.content} />
|
||||||
{/if}
|
{/if}
|
||||||
{#if pwaDescription}
|
{#if pwaAssetsHead.description}
|
||||||
<meta name="description" content={pwaDescription.content} />
|
<meta name="description" content={pwaAssetsHead.description.content} />
|
||||||
{/if}
|
{/if}
|
||||||
{#each pwaAssetsHead.links as link}
|
{#each pwaAssetsHead.links as link}
|
||||||
<link {...link} />
|
<link {...link} />
|
||||||
@@ -114,7 +91,7 @@
|
|||||||
<header>
|
<header>
|
||||||
<div class="navbar bg-primary text-primary-content">
|
<div class="navbar bg-primary text-primary-content">
|
||||||
<div class="navbar-start">
|
<div class="navbar-start">
|
||||||
<!-- <div class="dropdown">
|
<div class="dropdown">
|
||||||
<div tabindex="0" role="button" class="btn btn-ghost btn-circle">
|
<div tabindex="0" role="button" class="btn btn-ghost btn-circle">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
@@ -133,17 +110,32 @@
|
|||||||
<ul
|
<ul
|
||||||
class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-primary text-primary-content rounded-box w-52"
|
class="menu menu-sm dropdown-content mt-3 z-[1] p-2 shadow bg-primary text-primary-content rounded-box w-52"
|
||||||
>
|
>
|
||||||
|
<li><a href="/about">About</a></li>
|
||||||
<li>
|
<li>
|
||||||
<a href="https://github.com/jcreek/LivingDexTracker" target="_blank">Contribute</a>
|
<a href="https://github.com/jcreek/LivingDexTracker" target="_blank">Contribute</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div> -->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-center">
|
<div class="navbar-center">
|
||||||
<a class="btn btn-ghost text-xl" href="/">Living Dex Tracker</a>
|
<a class="btn btn-ghost text-xl" href="/">Living Dex Tracker</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="navbar-end">
|
<div class="navbar-end">
|
||||||
<ThemeToggle />
|
<button class="btn btn-ghost btn-circle">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="h-5 w-5"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
><path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</button>
|
||||||
<div class="dropdown dropdown-end">
|
<div class="dropdown dropdown-end">
|
||||||
{#if localUser}
|
{#if localUser}
|
||||||
<div tabindex="0" role="button" class="btn btn-ghost btn-circle avatar">
|
<div tabindex="0" role="button" class="btn btn-ghost btn-circle avatar">
|
||||||
@@ -157,11 +149,12 @@
|
|||||||
>
|
>
|
||||||
{#if localUser}
|
{#if localUser}
|
||||||
<li>
|
<li>
|
||||||
<a href="/my-pokedexes"> My Pokédexes </a>
|
<a href="/mydex"> My Dex </a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/backup-settings"> Backup Settings </a>
|
<a href="/profile"> Profile </a>
|
||||||
</li>
|
</li>
|
||||||
|
<li><a href="/settings">Settings</a></li>
|
||||||
<li><SignOut {supabase} on:signedOut={getUser} /></li>
|
<li><SignOut {supabase} on:signedOut={getUser} /></li>
|
||||||
{:else}
|
{:else}
|
||||||
<li><SignIn {supabase} on:signedIn={getUser} /></li>
|
<li><SignIn {supabase} on:signedIn={getUser} /></li>
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
import type { PageServerLoad } from './$types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Server-side load function for the homepage
|
|
||||||
*
|
|
||||||
* Fetches public statistics from the database and passes them to the page component.
|
|
||||||
* Stats are cached for 24 hours to improve performance.
|
|
||||||
*/
|
|
||||||
export const load: PageServerLoad = async ({ fetch }) => {
|
|
||||||
// Fetch stats from database
|
|
||||||
const statsResponse = await fetch('/api/stats');
|
|
||||||
const statsData = await statsResponse.json();
|
|
||||||
|
|
||||||
return {
|
|
||||||
stats: statsData.error ? null : statsData
|
|
||||||
};
|
|
||||||
};
|
|
||||||
+61
-312
@@ -1,392 +1,141 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy } from 'svelte';
|
||||||
import { user } from '$lib/stores/user.js';
|
import { user } from '$lib/stores/user.js';
|
||||||
import { type User } from '@supabase/auth-js';
|
import { type User } from '@supabase/auth-js';
|
||||||
import SignUp from '$lib/components/SignUp.svelte';
|
import SignUp from '$lib/components/SignUp.svelte';
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
let { supabase, stats } = data;
|
let { supabase } = data;
|
||||||
$: ({ supabase, stats } = data);
|
$: ({ supabase } = data);
|
||||||
|
|
||||||
let localUser: User | null;
|
let localUser: User | null;
|
||||||
const unsubscribe = user.subscribe((value) => {
|
const unsubscribe = user.subscribe((value) => {
|
||||||
localUser = value;
|
localUser = value;
|
||||||
});
|
});
|
||||||
onDestroy(unsubscribe);
|
onDestroy(unsubscribe);
|
||||||
|
|
||||||
let isCheckingSession = true;
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
checkSessionAndRedirect();
|
|
||||||
});
|
|
||||||
|
|
||||||
async function checkSessionAndRedirect() {
|
|
||||||
try {
|
|
||||||
const {
|
|
||||||
data: { session }
|
|
||||||
} = await supabase.auth.getSession();
|
|
||||||
|
|
||||||
if (session) {
|
|
||||||
await goto('/my-pokedexes');
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error checking session:', error);
|
|
||||||
} finally {
|
|
||||||
isCheckingSession = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleSignedUp() {
|
|
||||||
await goto('/welcome');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format large numbers (e.g., 1000 -> 1K, 1000000 -> 1M)
|
|
||||||
function formatNumber(num: number): string {
|
|
||||||
if (num >= 1000000) {
|
|
||||||
return (num / 1000000).toFixed(1).replace(/\.0$/, '') + 'M';
|
|
||||||
}
|
|
||||||
if (num >= 1000) {
|
|
||||||
return (num / 1000).toFixed(0) + 'K';
|
|
||||||
}
|
|
||||||
return num.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get formatted stats or fallback to 0
|
|
||||||
let pokemonCaught = '0';
|
|
||||||
let users = '0';
|
|
||||||
let livingDexesCompleted = '0';
|
|
||||||
$: {
|
|
||||||
pokemonCaught = formatNumber(stats?.pokemonCaught ?? 0);
|
|
||||||
users = formatNumber(stats?.users ?? 0);
|
|
||||||
livingDexesCompleted = formatNumber(stats?.livingDexesCompleted ?? 0);
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<div class="hero bg-base-100 my-36">
|
||||||
<title>Living Dex Tracker - Track Your Pokédex Journey</title>
|
|
||||||
<meta
|
|
||||||
name="description"
|
|
||||||
content="A free, open source tool to track your Living Pokédex progress. Join thousands of trainers worldwide in completing their collection."
|
|
||||||
/>
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
{#if isCheckingSession}
|
|
||||||
<!-- Loading placeholder while checking session -->
|
|
||||||
<div class="hero bg-base-100 my-36">
|
|
||||||
<div class="hero-content flex-col">
|
|
||||||
<span class="loading loading-spinner loading-lg"></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<!-- Hero Section -->
|
|
||||||
<div class="hero bg-base-100 my-36">
|
|
||||||
<div class="hero-content flex-col lg:flex-row-reverse">
|
<div class="hero-content flex-col lg:flex-row-reverse">
|
||||||
<div class="text-center lg:text-left">
|
<div class="text-center lg:text-left">
|
||||||
<div class="flex flex-wrap gap-2 mb-4">
|
<h1 class="text-5xl font-bold">Start Your Pokédex Journey!</h1>
|
||||||
<div class="badge badge-primary badge-lg gap-1">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-4 w-4"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Free
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-secondary badge-lg gap-1">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-4 w-4"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Open Source
|
|
||||||
</div>
|
|
||||||
<div class="badge badge-accent badge-lg gap-1">
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-4 w-4"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="currentColor"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
d="M.458 10C1.732 5.943 5.522 3 10 3s8.268 2.943 9.542 7c-1.274 4.057-5.064 7-9.542 7S1.732 14.057.458 10zM14 10a4 4 0 11-8 0 4 4 0 018 0z"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Offline-friendly
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<h1 class="text-5xl font-bold mb-6">Start Your Pokédex Journey!</h1>
|
|
||||||
<p class="text-xl mb-6 text-base-content/80">
|
|
||||||
Track your progress towards a complete Living Pokédex — one of every Pokémon, actively
|
|
||||||
maintained across your boxes. Join thousands of trainers worldwide.
|
|
||||||
</p>
|
|
||||||
<div class="flex flex-wrap gap-3 justify-center lg:justify-start">
|
|
||||||
<a
|
|
||||||
href="https://discord.gg/2ytj4pkUPY"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="btn btn-primary btn-lg"
|
|
||||||
aria-label="Join the Living Dex Tracker Discord community"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Join Discord
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://github.com/jcreek/LivingDexTracker"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
class="btn btn-outline btn-lg"
|
|
||||||
aria-label="View the Living Dex Tracker project on GitHub"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
class="h-5 w-5"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Contribute on GitHub
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="card shrink-0 w-full max-w-sm shadow-2xl bg-neutral">
|
<div class="card shrink-0 w-full max-w-sm shadow-2xl bg-neutral">
|
||||||
<div class="card-body">
|
<SignUp {supabase} />
|
||||||
<h2 class="card-title text-2xl mb-4">Get Started Free</h2>
|
|
||||||
<SignUp {supabase} on:signedUp={handleSignedUp} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Stats Section -->
|
<div
|
||||||
<div class="bg-base-200 py-16">
|
class="md:container md:mx-auto justify-self-center flex justify-center items-center h-full flex-col mb-10"
|
||||||
<div class="container mx-auto px-4">
|
>
|
||||||
<div class="stats stats-vertical lg:stats-horizontal shadow bg-neutral text-center w-full">
|
<div class="stats stats-vertical lg:stats-horizontal shadow bg-neutral text-center">
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<div class="stat-title">Pokémon caught</div>
|
<div class="stat-title">Pokémon caught</div>
|
||||||
<div class="stat-value text-primary">{pokemonCaught}</div>
|
<div class="stat-value">310K</div>
|
||||||
|
<div class="stat-desc">Since January 2024</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<div class="stat-title">Users</div>
|
<div class="stat-title">New Users</div>
|
||||||
<div class="stat-value text-primary">{users}</div>
|
<div class="stat-value">4,200</div>
|
||||||
|
<div class="stat-desc">↗︎ 400 (22%)</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stat">
|
<div class="stat">
|
||||||
<div class="stat-title">Living Dexes Completed</div>
|
<div class="stat-title">Living Dexes Completed</div>
|
||||||
<div class="stat-value text-primary">{livingDexesCompleted}</div>
|
<div class="stat-value">1,200</div>
|
||||||
</div>
|
<div class="stat-desc">↘︎ 90 (14%)</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- What is a Living Dex Section -->
|
<div class="features mt-8">
|
||||||
<div class="py-16 bg-base-100">
|
<h1 class="flex justify-center text-4xl font-bold mb-5">Features</h1>
|
||||||
<div class="container mx-auto px-4 max-w-4xl">
|
|
||||||
<div class="card bg-base-100 shadow-xl">
|
|
||||||
<div class="card-body">
|
|
||||||
<h2 class="card-title text-3xl mb-4">What is a Living Dex?</h2>
|
|
||||||
<p class="text-lg text-base-content/80">
|
|
||||||
A Living Dex is a complete Pokédex where you keep one of every Pokémon in your boxes
|
|
||||||
(often including forms/variants). Living Dex Tracker helps you build and maintain that
|
|
||||||
collection with filters, notes, and progress tracking.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Features Section -->
|
<ul class="space-y-6">
|
||||||
<div class="py-16 bg-base-200">
|
<li class="p-6 rounded-lg shadow-md bg-neutral">
|
||||||
<div class="container mx-auto px-4 max-w-6xl">
|
<div class="flex items-start space-x-4">
|
||||||
<h2 class="text-4xl font-bold mb-12 text-center">Why Choose Living Dex Tracker?</h2>
|
|
||||||
|
|
||||||
<div class="grid md:grid-cols-2 gap-6">
|
|
||||||
<div class="card bg-neutral shadow-xl">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="flex items-start gap-4">
|
|
||||||
<div class="flex-shrink-0">
|
|
||||||
<svg
|
<svg
|
||||||
class="w-10 h-10 text-green-500"
|
class="w-8 h-8 text-green-500 flex-shrink-0"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
aria-hidden="true"
|
|
||||||
>
|
>
|
||||||
<path
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
|
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="card-title text-xl mb-2">Social & Shareable</h2>
|
<h2 class="text-lg font-semibold">Social</h2>
|
||||||
<p class="text-base-content/80">
|
<p>
|
||||||
Easily share your Pokédex journey with friends, or find theirs. If you'd rather go
|
Easily share your Pokédex journey with friends, or find theirs. If you'd rather go it
|
||||||
it alone, that's okay too!
|
alone, that's okay too!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</div>
|
<li class="p-6 rounded-lg shadow-md bg-neutral">
|
||||||
|
<div class="flex items-start space-x-4">
|
||||||
<div class="card bg-neutral shadow-xl">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="flex items-start gap-4">
|
|
||||||
<div class="flex-shrink-0">
|
|
||||||
<svg
|
<svg
|
||||||
class="w-10 h-10 text-green-500"
|
class="w-8 h-8 text-green-500 flex-shrink-0"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
aria-hidden="true"
|
|
||||||
>
|
>
|
||||||
<path
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
|
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="card-title text-xl mb-2">Free & Open Source</h2>
|
<h2 class="text-lg font-semibold">Free & Open Source</h2>
|
||||||
<p class="text-base-content/80">
|
<p>
|
||||||
Completely open source and free to use, enabling the community to contribute
|
Completely open source and free to use, enabling the community to contribute updates
|
||||||
updates as soon as new Pokémon are released.
|
as soon as new Pokémon are released.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</div>
|
<li class="p-6 rounded-lg shadow-md bg-neutral">
|
||||||
|
<div class="flex items-start space-x-4">
|
||||||
<div class="card bg-neutral shadow-xl">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="flex items-start gap-4">
|
|
||||||
<div class="flex-shrink-0">
|
|
||||||
<svg
|
<svg
|
||||||
class="w-10 h-10 text-green-500"
|
class="w-8 h-8 text-green-500 flex-shrink-0"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
aria-hidden="true"
|
|
||||||
>
|
>
|
||||||
<path
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"
|
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="card-title text-xl mb-2">Advanced Filtering</h2>
|
<h2 class="text-lg font-semibold">Easy to use with advanced filtering</h2>
|
||||||
<p class="text-base-content/80">
|
<p>
|
||||||
Track simple progress or tackle harder variants like a Living Origin Form Dex with
|
If you just want to track your progress completing your Pokédex, you can do that. But
|
||||||
our powerful filtering options for targeted catching sessions.
|
if you are attempting a harder variant, like a Living Origin Forme Dex, you might find
|
||||||
|
our advanced filtering options helpful for tracking target Pokémon for specific
|
||||||
|
catching sessions.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</li>
|
||||||
</div>
|
<li class="p-6 rounded-lg shadow-md bg-neutral">
|
||||||
|
<div class="flex items-start space-x-4">
|
||||||
<div class="card bg-neutral shadow-xl">
|
|
||||||
<div class="card-body">
|
|
||||||
<div class="flex items-start gap-4">
|
|
||||||
<div class="flex-shrink-0">
|
|
||||||
<svg
|
<svg
|
||||||
class="w-10 h-10 text-green-500"
|
class="w-8 h-8 text-green-500 flex-shrink-0"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
aria-hidden="true"
|
|
||||||
>
|
>
|
||||||
<path
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
stroke-width="2"
|
|
||||||
d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08.402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
||||||
></path>
|
></path>
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h2 class="card-title text-xl mb-2">100% free</h2>
|
<h2 class="text-lg font-semibold">100% free</h2>
|
||||||
<p class="text-base-content/80">
|
<p>Did we mention it's completely free to use? Oh, we did? Good. Because it is.</p>
|
||||||
Did we mention it's completely free to use? Oh, we did? Good. Because it is.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- CTA Section -->
|
|
||||||
<div class="py-16 bg-base-100">
|
|
||||||
<div class="container mx-auto px-4 text-center">
|
|
||||||
<h2 class="text-4xl font-bold mb-6">Ready to Start Your Journey?</h2>
|
|
||||||
<p class="text-xl mb-8 text-base-content/80 max-w-2xl mx-auto">
|
|
||||||
Get started today with tracking your Living Pokédex progress. It's free, open source, and
|
|
||||||
built with love for the Pokémon community.
|
|
||||||
</p>
|
|
||||||
<div class="flex flex-wrap gap-4 justify-center">
|
|
||||||
<div class="card shrink-0 w-full max-w-sm shadow-2xl bg-neutral">
|
|
||||||
<div class="card-body">
|
|
||||||
<h3 class="card-title text-xl mb-4">Sign Up Now</h3>
|
|
||||||
<SignUp {supabase} on:signedUp={handleSignedUp} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Legal Section -->
|
|
||||||
<div class="py-8 bg-base-200">
|
|
||||||
<div class="container mx-auto px-4 max-w-4xl">
|
|
||||||
<div class="card bg-base-100 shadow-xl">
|
|
||||||
<div class="card-body">
|
|
||||||
<h2 class="card-title text-lg mb-2">Legal Disclaimer</h2>
|
|
||||||
<p class="text-sm text-base-content/70">
|
|
||||||
Living Dex Tracker is a fan-made project. We do not claim ownership of any Pokémon
|
|
||||||
characters, images, or other content featured on this website. This project is not
|
|
||||||
affiliated with, endorsed, sponsored, or specifically approved by Nintendo, Game Freak,
|
|
||||||
or The Pokémon Company.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|||||||
@@ -0,0 +1,327 @@
|
|||||||
|
<svelte:head>
|
||||||
|
<title>About Us</title>
|
||||||
|
<meta name="description" content="About this app" />
|
||||||
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Pixelify+Sans:wght@400..700&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&family=Staatliches&display=swap"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
</svelte:head>
|
||||||
|
|
||||||
|
<div class="content h-full bg-base inline-block">
|
||||||
|
<div id="grad">
|
||||||
|
<div id="banner-content">
|
||||||
|
<p class=" text-xs opacity-70 tracking-wide">Learn</p>
|
||||||
|
<h2 class=" mt-0 pt-0 text-5xl tracking-widest text-center font-bold p-24">
|
||||||
|
About<br /> Us
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="introduction">
|
||||||
|
<p class="font-semibold text-xl mb-5 ml-5">
|
||||||
|
Introducing <span class="typewriter-text underline decoration-accent">Living Dex Tracker</span
|
||||||
|
>
|
||||||
|
</p>
|
||||||
|
<p class="text-base mt-10 mb-5 ml-5 mr-5">
|
||||||
|
<img src="/placeholder-bulb.png" alt="bulb" class="float-right w-28" />
|
||||||
|
Living Dex Tracker is dolor sit amet, consectetur adipiscing elit. Proin dignissim risus eu quam
|
||||||
|
feugiat malesuada. Vivamus arcu sapien, feugiat sed lacus ut, malesuada congue nibh. In lacinia
|
||||||
|
lacus quis bibendum pulvinar. Aliquam in suscipit risus. Aliquam ut justo dolor.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="font-semibold text-xl mt-20 mb-5 ml-5">Features</p>
|
||||||
|
|
||||||
|
<!-- TODO (#41) - Make this a card carousel -->
|
||||||
|
<div class="card md:card-side bg-base-00 shadow-m">
|
||||||
|
<figure>
|
||||||
|
<img src="/OIG3.jpeg" alt="Album" />
|
||||||
|
</figure>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-title">Player Dex Search</p>
|
||||||
|
<p>Find and explore your friends' Pokémon collections effortlessly.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="bg-neutral pb-20">
|
||||||
|
<p class="font-semibold text-white text-xl mt-0 mb-5 ml-5">Meet The Team</p>
|
||||||
|
<div class="avatar flex items-center justify-end mb-20">
|
||||||
|
<p class="text-m mb-5 ml-5 mr-5">Team Member 1</p>
|
||||||
|
<div class="w-24 rounded-full flex justify-end">
|
||||||
|
<img src="/OIG5.jpg" alt="profile" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="avatar">
|
||||||
|
<div class="w-24 rounded-full">
|
||||||
|
<img src="/OIG5.jpg" alt="profile " />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="text-m mb-5 ml-5 mr-5">Team Member 2</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="project-details">
|
||||||
|
<p class="font-semibold text-xl mt-10 mb-5 ml-5">The Developement</p>
|
||||||
|
<p class="text-sm mb-5 ml-5 mr-5">
|
||||||
|
Share insights into the development process, challenges faced, and any interesting anecdotes
|
||||||
|
or milestones achieved during the project's journey.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul class="timeline timeline-vertical">
|
||||||
|
<li>
|
||||||
|
<div class="timeline-start timeline-box">Example</div>
|
||||||
|
<div class="timeline-middle">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-5 h-5 text-primary"
|
||||||
|
><path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<hr class="bg-primary" />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<hr class="bg-primary" />
|
||||||
|
<div class="timeline-middle">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-5 h-5 text-primary"
|
||||||
|
><path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="timeline-end timeline-box">Example</div>
|
||||||
|
<hr class="bg-primary" />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<hr class="bg-primary" />
|
||||||
|
<div class="timeline-start timeline-box">Example</div>
|
||||||
|
<div class="timeline-middle">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-5 h-5 text-primary"
|
||||||
|
><path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<hr />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<hr />
|
||||||
|
<div class="timeline-middle">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-5 h-5"
|
||||||
|
><path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="timeline-end timeline-box">Example</div>
|
||||||
|
<hr />
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<hr />
|
||||||
|
<div class="timeline-start timeline-box">Example</div>
|
||||||
|
<div class="timeline-middle">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-5 h-5"
|
||||||
|
><path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="font-semibold text-xl mt-10 mb-5 ml-5">Join Us On Discord!</p>
|
||||||
|
|
||||||
|
<div id="contact-information ">
|
||||||
|
<a href="https://discord.gg/2ytj4pkUPY">
|
||||||
|
<button
|
||||||
|
class="relative inline-flex items-center justify-center w-16 p-0.5 ml-5 mb-20 me-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-gradient-to-br from-cyan-500 to-blue-500 group-hover:from-cyan-500 group-hover:to-blue-500 hover:text-white dark:text-white focus:ring-4 focus:outline-none focus:ring-cyan-200 dark:focus:ring-cyan-800"
|
||||||
|
>
|
||||||
|
<img src="/discord1.svg" class="w-12" /></button
|
||||||
|
>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="contact-form">
|
||||||
|
<p class="font-semibold text-xl mt-0 mb-5 text-white pt-10">Contact Form</p>
|
||||||
|
<input type="text" name="first" placeholder="First Name" autocomplete="off" required />
|
||||||
|
<input type="text" name="last" placeholder="Last Name" autocomplete="off" required />
|
||||||
|
<input type="email" name="Email" placeholder="Email Address" autocomplete="off" required />
|
||||||
|
<textarea
|
||||||
|
rows="5"
|
||||||
|
cols="50"
|
||||||
|
name="message"
|
||||||
|
placeholder="Enter text"
|
||||||
|
autocomplete="off"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
<button type="submit" id="submit-button">Send Message</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="legal-information">
|
||||||
|
<p class="font-semibold text-xl mt-0 mb-5 ml-5 text-white pt-10">Legal</p>
|
||||||
|
|
||||||
|
<p class="text-sm mb-5 ml-5 mr-5">
|
||||||
|
Living Dex Tracker is a fan-made website dedicated to providing information about Pokemon
|
||||||
|
creatures. We do not claim ownership of any Pokemon characters, images, or other content
|
||||||
|
featured on this website.
|
||||||
|
</p>
|
||||||
|
<p class="text-sm mb-5 ml-5 mr-5">
|
||||||
|
We do not generate revenue from the use of Pokemon content. Any advertisements or sponsored
|
||||||
|
content on this website are unrelated to Pokemon and are used solely to support the
|
||||||
|
maintenance and operation of the website.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="Acknowledgments">
|
||||||
|
<p class="font-semibold text-xl mt-0 mb-5 ml-5 text-white pt-10">Acknowledgments</p>
|
||||||
|
<p class="text-sm mb-5 ml-5 mr-5">
|
||||||
|
Express gratitude to any individuals or organisations that have contributed to the project's
|
||||||
|
success, including sponsors, supporters, or open-source contributors.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#banner-content {
|
||||||
|
padding-top: 170px;
|
||||||
|
}
|
||||||
|
#grad {
|
||||||
|
font-family: 'Pixelify Sans', sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 422px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: linear-gradient(45deg, #d2001a, #7462ff, #f48e21, #23d5ab);
|
||||||
|
color: #fff;
|
||||||
|
background-size: 300% 300%;
|
||||||
|
animation: color 12s ease-in-out infinite;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
@keyframes color {
|
||||||
|
0% {
|
||||||
|
background-position: 0 50%;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-position: 100% 50%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 0 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#introduction .font-semibold {
|
||||||
|
font-family: 'Staatliches', sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
font-style: normal;
|
||||||
|
font-size: 25px;
|
||||||
|
padding-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form {
|
||||||
|
background-color: rgb(216, 224, 178);
|
||||||
|
width: 380px;
|
||||||
|
height: 590px;
|
||||||
|
border-radius: 20px;
|
||||||
|
margin-bottom: 40px;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.contact-form > p {
|
||||||
|
margin-left: 9px;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
background-color: rgb(156, 186, 139);
|
||||||
|
width: 70%;
|
||||||
|
margin-left: 12%;
|
||||||
|
padding: 16px 16px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-color: rgb(131, 167, 124);
|
||||||
|
border-width: 2px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-family: 'Staatliches', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
background-color: rgb(156, 186, 139);
|
||||||
|
width: 70%;
|
||||||
|
margin-left: 12%;
|
||||||
|
padding: 16px 16px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border-color: rgb(83, 145, 50);
|
||||||
|
margin-bottom: 25px;
|
||||||
|
font-family: 'Staatliches', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:focus-within {
|
||||||
|
outline: none;
|
||||||
|
border-color: rgb(169, 227, 157);
|
||||||
|
border-width: 3px;
|
||||||
|
font-family: 'Staatliches', sans-serif;
|
||||||
|
}
|
||||||
|
textarea:focus-within {
|
||||||
|
outline: none;
|
||||||
|
border-color: rgb(169, 227, 157);
|
||||||
|
border-width: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#submit-button {
|
||||||
|
background-color: rgb(185, 201, 135);
|
||||||
|
border-radius: 20px;
|
||||||
|
border-color: #fff;
|
||||||
|
padding: 10px 18px;
|
||||||
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
margin: auto;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
opacity: 80%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { dev } from '$app/environment';
|
||||||
|
|
||||||
|
// we don't need any JS on this page, though we'll load
|
||||||
|
// it in dev so that we get hot module replacement...
|
||||||
|
export const csr = dev;
|
||||||
|
|
||||||
|
// since there's no dynamic data here, we can prerender
|
||||||
|
// it so that it gets served as a static asset in prod
|
||||||
|
export const prerender = true;
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
import { json } from '@sveltejs/kit';
|
||||||
|
import { dbConnect, dbDisconnect } from '$lib/utils/db';
|
||||||
|
import { type CatchRecord } from '$lib/models/CatchRecord';
|
||||||
|
import CatchRecordRepository from '$lib/repositories/CatchRecordRepository';
|
||||||
|
|
||||||
|
export const GET = async () => {
|
||||||
|
let catchData = null as CatchRecord[] | null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dbConnect();
|
||||||
|
const repo = new CatchRecordRepository();
|
||||||
|
catchData = await repo.findAll();
|
||||||
|
// order by pokedexEntryId property, ascending
|
||||||
|
catchData = catchData.sort((a, b) => a.pokedexEntryId - b.pokedexEntryId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
} finally {
|
||||||
|
dbDisconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(catchData);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PUT = async ({ request }) => {
|
||||||
|
try {
|
||||||
|
const data: Partial<CatchRecord> = await request.json();
|
||||||
|
await dbConnect();
|
||||||
|
const repo = new CatchRecordRepository();
|
||||||
|
const upsertedRecord = await repo.upsert(data);
|
||||||
|
return json(upsertedRecord);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
throw error(500, 'Internal Server Error');
|
||||||
|
} finally {
|
||||||
|
await dbDisconnect();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const POST = async ({ request }) => {
|
||||||
|
try {
|
||||||
|
const records: Partial<CatchRecord>[] = await request.json();
|
||||||
|
await dbConnect();
|
||||||
|
const repo = new CatchRecordRepository();
|
||||||
|
|
||||||
|
const insertedRecords = [];
|
||||||
|
for (const record of records) {
|
||||||
|
const upsertedRecord = await repo.upsert(record);
|
||||||
|
insertedRecords.push(upsertedRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
return json(insertedRecords);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
throw error(500, 'Internal Server Error');
|
||||||
|
} finally {
|
||||||
|
await dbDisconnect();
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import { json } from '@sveltejs/kit';
|
||||||
|
import { dbConnect, dbDisconnect } from '$lib/utils/db';
|
||||||
|
import CombinedDataRepository from '$lib/repositories/CombinedDataRepository';
|
||||||
|
|
||||||
|
export const GET = async ({ url }) => {
|
||||||
|
const page = parseInt(url.searchParams.get('page') || '1', 10);
|
||||||
|
const limit = parseInt(url.searchParams.get('limit') || '20', 10);
|
||||||
|
const enableForms = url.searchParams.get('enableForms') === 'true';
|
||||||
|
const region = url.searchParams.get('region');
|
||||||
|
const game = url.searchParams.get('game');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dbConnect();
|
||||||
|
const repo = new CombinedDataRepository();
|
||||||
|
const combinedData = await repo.findCombinedData(page, limit, enableForms, region, game);
|
||||||
|
|
||||||
|
if (combinedData.length === 0) {
|
||||||
|
return json({ error: 'No combined data found' }, { status: 404 });
|
||||||
|
}
|
||||||
|
const totalCount = await repo.countCombinedData(enableForms, region, game);
|
||||||
|
const totalPages = Math.ceil(totalCount / limit);
|
||||||
|
|
||||||
|
return json({ combinedData, totalPages });
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return json({ error: 'Internal Server Error' }, { status: 500 });
|
||||||
|
} finally {
|
||||||
|
dbDisconnect();
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import { json } from '@sveltejs/kit';
|
||||||
|
import { dbConnect, dbDisconnect } from '$lib/utils/db';
|
||||||
|
import CombinedDataRepository from '$lib/repositories/CombinedDataRepository';
|
||||||
|
|
||||||
|
export const GET = async ({ url }) => {
|
||||||
|
const enableForms = url.searchParams.get('enableForms') === 'true';
|
||||||
|
const region = url.searchParams.get('region');
|
||||||
|
const game = url.searchParams.get('game');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await dbConnect();
|
||||||
|
const repo = new CombinedDataRepository();
|
||||||
|
const combinedData = await repo.findAllCombinedData(enableForms, region, game);
|
||||||
|
|
||||||
|
if (combinedData.length === 0) {
|
||||||
|
return json({ error: 'No combined data found' }, { status: 404 });
|
||||||
|
}
|
||||||
|
return json(combinedData);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return json({ error: 'Internal Server Error' }, { status: 500 });
|
||||||
|
} finally {
|
||||||
|
dbDisconnect();
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import { json } from '@sveltejs/kit';
|
|
||||||
import type { RequestEvent } from '@sveltejs/kit';
|
|
||||||
import PokedexExportIntegrationRepository from '$lib/repositories/PokedexExportIntegrationRepository';
|
|
||||||
import { requireAuth } from '$lib/utils/auth';
|
|
||||||
|
|
||||||
export const GET = async (event: RequestEvent) => {
|
|
||||||
try {
|
|
||||||
const userId = await requireAuth(event);
|
|
||||||
|
|
||||||
const { session } = await event.locals.safeGetSession();
|
|
||||||
if (session) {
|
|
||||||
await event.locals.supabase.auth.setSession(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
const repo = new PokedexExportIntegrationRepository(event.locals.supabase, userId, null);
|
|
||||||
const integrations = await repo.listAll();
|
|
||||||
|
|
||||||
const safe = integrations.map((integration) => ({
|
|
||||||
id: integration._id,
|
|
||||||
provider: integration.provider,
|
|
||||||
enabled: integration.enabled,
|
|
||||||
fileName: integration.fileName,
|
|
||||||
folderId: integration.folderId,
|
|
||||||
path: integration.path,
|
|
||||||
metadata: integration.metadata,
|
|
||||||
lastExportedAt: integration.lastExportedAt,
|
|
||||||
lastError: integration.lastError
|
|
||||||
}));
|
|
||||||
|
|
||||||
return json(safe);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
if (err && typeof err === 'object' && 'status' in err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
return json({ error: 'Internal Server Error' }, { status: 500 });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
import { json } from '@sveltejs/kit';
|
|
||||||
import type { RequestEvent } from '@sveltejs/kit';
|
|
||||||
import { requireAuth } from '$lib/utils/auth';
|
|
||||||
|
|
||||||
const ALLOWED_PROVIDERS = new Set(['google_drive', 'dropbox']);
|
|
||||||
|
|
||||||
export const PUT = async (event: RequestEvent) => {
|
|
||||||
try {
|
|
||||||
const userId = await requireAuth(event);
|
|
||||||
const { provider } = event.params;
|
|
||||||
|
|
||||||
if (!provider || !ALLOWED_PROVIDERS.has(provider)) {
|
|
||||||
return json({ error: 'Invalid provider' }, { status: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const { session } = await event.locals.safeGetSession();
|
|
||||||
if (session) {
|
|
||||||
await event.locals.supabase.auth.setSession(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
let body: {
|
|
||||||
folderId?: string | null;
|
|
||||||
path?: string | null;
|
|
||||||
};
|
|
||||||
try {
|
|
||||||
body = (await event.request.json()) as {
|
|
||||||
folderId?: string | null;
|
|
||||||
path?: string | null;
|
|
||||||
};
|
|
||||||
} catch (err) {
|
|
||||||
if (err instanceof SyntaxError) {
|
|
||||||
return new Response('Malformed JSON', { status: 400 });
|
|
||||||
}
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
|
|
||||||
const patch: Record<string, unknown> = {};
|
|
||||||
if (body.folderId !== undefined) patch.folderId = body.folderId;
|
|
||||||
if (body.path !== undefined) patch.path = body.path;
|
|
||||||
if (Object.keys(patch).length === 0) {
|
|
||||||
return json({ error: 'No fields to update' }, { status: 400 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const { data, error } = await event.locals.supabase
|
|
||||||
.from('pokedex_export_integrations')
|
|
||||||
.update(patch)
|
|
||||||
.eq('userId', userId)
|
|
||||||
.is('pokedexId', null)
|
|
||||||
.eq('provider', provider)
|
|
||||||
.select('id, provider, enabled, fileName, folderId, path, metadata, lastExportedAt, lastError')
|
|
||||||
.maybeSingle();
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error(error);
|
|
||||||
return json({ error: 'Internal Server Error' }, { status: 500 });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data === null) {
|
|
||||||
return json({ error: 'Integration not found' }, { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
return json(data);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
if (err && typeof err === 'object' && 'status' in err) {
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
return json({ error: 'Internal Server Error' }, { status: 500 });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
import { json } from '@sveltejs/kit';
|
|
||||||
import type { RequestHandler } from './$types';
|
|
||||||
import { listGameDexes } from '$lib/services/PokedexDexScopeService';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GET /api/game-dexes
|
|
||||||
* Returns game dexes grouped by game display name.
|
|
||||||
*/
|
|
||||||
export const GET: RequestHandler = async ({ locals }) => {
|
|
||||||
try {
|
|
||||||
const { gameDexes, gameOrder, games } = await listGameDexes(locals.supabase);
|
|
||||||
return json({ gameDexes, gameOrder, games });
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Unexpected error fetching game dexes:', err);
|
|
||||||
return json({ error: 'Internal server error' }, { status: 500 });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
import { json } from '@sveltejs/kit';
|
|
||||||
import type { RequestHandler } from './$types';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GET /api/games
|
|
||||||
* Returns all games from the games table, sorted by release year descending (newest first)
|
|
||||||
*/
|
|
||||||
export const GET: RequestHandler = async ({ locals }) => {
|
|
||||||
const { supabase } = locals;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Query games table for all games, sorted by release year descending
|
|
||||||
const { data, error } = await supabase
|
|
||||||
.from('games')
|
|
||||||
.select('displayName, releaseYear')
|
|
||||||
.order('releaseYear', { ascending: false })
|
|
||||||
.order('displayName', { ascending: true }); // Secondary sort by name for same year
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
console.error('Error fetching games:', error);
|
|
||||||
return json({ error: 'Failed to fetch games' }, { status: 500 });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract just the display names
|
|
||||||
const gameNames = data.map((row) => row.displayName);
|
|
||||||
|
|
||||||
return json({ games: gameNames });
|
|
||||||
} catch (err) {
|
|
||||||
console.error('Unexpected error fetching games:', err);
|
|
||||||
return json({ error: 'Internal server error' }, { status: 500 });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user