From 19a571e3150a48f2249761c4b3b817503d0c1633 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Sun, 4 Jan 2026 22:06:36 +0000 Subject: [PATCH 1/4] feat(#67): Add support for multiple pokedexes per user --- src/lib/components/pokedex/PokedexCard.svelte | 51 +++++ .../pokedex/PokedexEntryCatchRecord.svelte | 118 ++++++----- src/lib/components/pokedex/PokedexForm.svelte | 103 +++++++++ .../components/pokedex/PokedexSidebar.svelte | 27 +++ .../pokedex/PokedexViewBoxes.svelte | 14 +- .../components/pokedex/PokedexViewList.svelte | 2 + src/lib/models/CatchRecord.ts | 2 + src/lib/models/Pokedex.ts | 25 +++ src/lib/models/PokedexEntry.ts | 34 +++ src/lib/repositories/CatchRecordRepository.ts | 24 ++- .../repositories/CombinedDataRepository.ts | 142 ++++++++++--- .../repositories/PokedexEntryRepository.ts | 20 +- src/lib/repositories/PokedexRepository.ts | 108 ++++++++++ src/lib/utils/regionalDexMapping.ts | 141 +++++++++++++ src/routes/+layout.svelte | 2 +- src/routes/api/combined-data/+server.ts | 52 ----- src/routes/api/combined-data/all/+server.ts | 36 ---- src/routes/api/pokedexes/+server.ts | 47 +++++ src/routes/api/pokedexes/[id]/+server.ts | 107 ++++++++++ .../[id]}/catch-records/+server.ts | 68 ++++-- .../pokedexes/[id]/combined-data/+server.ts | 72 +++++++ src/routes/my-pokedexes/+page.svelte | 196 ++++++++++++++++++ src/routes/pokedex/[id]/+page.server.ts | 28 +++ .../{mydex => pokedex/[id]}/+page.svelte | 45 ++-- src/routes/signin/+page.svelte | 2 +- .../20250127000001_add_pokedexes_table.sql | 51 +++++ ...000002_add_pokedex_id_to_catch_records.sql | 74 +++++++ ...0260103181600_add_regional_dex_numbers.sql | 25 +++ 28 files changed, 1401 insertions(+), 215 deletions(-) create mode 100644 src/lib/components/pokedex/PokedexCard.svelte create mode 100644 src/lib/components/pokedex/PokedexForm.svelte create mode 100644 src/lib/models/Pokedex.ts create mode 100644 src/lib/repositories/PokedexRepository.ts create mode 100644 src/lib/utils/regionalDexMapping.ts delete mode 100644 src/routes/api/combined-data/+server.ts delete mode 100644 src/routes/api/combined-data/all/+server.ts create mode 100644 src/routes/api/pokedexes/+server.ts create mode 100644 src/routes/api/pokedexes/[id]/+server.ts rename src/routes/api/{ => pokedexes/[id]}/catch-records/+server.ts (55%) create mode 100644 src/routes/api/pokedexes/[id]/combined-data/+server.ts create mode 100644 src/routes/my-pokedexes/+page.svelte create mode 100644 src/routes/pokedex/[id]/+page.server.ts rename src/routes/{mydex => pokedex/[id]}/+page.svelte (85%) create mode 100644 supabase/migrations/20250127000001_add_pokedexes_table.sql create mode 100644 supabase/migrations/20250127000002_add_pokedex_id_to_catch_records.sql create mode 100644 supabase/migrations/20260103181600_add_regional_dex_numbers.sql diff --git a/src/lib/components/pokedex/PokedexCard.svelte b/src/lib/components/pokedex/PokedexCard.svelte new file mode 100644 index 0000000..1cb6949 --- /dev/null +++ b/src/lib/components/pokedex/PokedexCard.svelte @@ -0,0 +1,51 @@ + + +
+
+

+ {pokedex.name} +

+ + {#if pokedex.description} +

{pokedex.description}

+ {/if} + +
+ {#each typeBadges as badge} + {badge} + {/each} +
+ + {#if pokedex.gameScope} +
+ Game: + {pokedex.gameScope} +
+ {:else} +
+ Scope: All Games +
+ {/if} + +
+ + + +
+
+
diff --git a/src/lib/components/pokedex/PokedexEntryCatchRecord.svelte b/src/lib/components/pokedex/PokedexEntryCatchRecord.svelte index 85b931d..659126c 100644 --- a/src/lib/components/pokedex/PokedexEntryCatchRecord.svelte +++ b/src/lib/components/pokedex/PokedexEntryCatchRecord.svelte @@ -10,6 +10,7 @@ export let showForms: 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) { @@ -17,6 +18,7 @@ _id: '', // Empty string, not temp ID - will be created by server userId: userId || '', pokedexEntryId: pokedexEntry._id, + pokedexId: pokedexId, haveToEvolve: false, caught: false, inHome: false, @@ -83,74 +85,76 @@ -
-
-
- -
-
-
-
- -
-
-
-
- -
-
- {#if pokedexEntry.canGigantamax && showForms} + {#if catchRecord} +
- {/if} -

- - -

-
+
+
+ +
+
+
+
+ +
+
+ {#if pokedexEntry.canGigantamax && showForms} +
+
+ +
+
+ {/if} +

+ + +

+
+ {/if}
{#if showOrigins} diff --git a/src/lib/components/pokedex/PokedexForm.svelte b/src/lib/components/pokedex/PokedexForm.svelte new file mode 100644 index 0000000..02a2656 --- /dev/null +++ b/src/lib/components/pokedex/PokedexForm.svelte @@ -0,0 +1,103 @@ + + +
+ + +
+ +
+ + +
+ +
+ +
+ + + + +
+
+ +
+ + +
+ + diff --git a/src/lib/components/pokedex/PokedexSidebar.svelte b/src/lib/components/pokedex/PokedexSidebar.svelte index fb25d38..28790b5 100644 --- a/src/lib/components/pokedex/PokedexSidebar.svelte +++ b/src/lib/components/pokedex/PokedexSidebar.svelte @@ -1,6 +1,8 @@ diff --git a/src/lib/components/pokedex/PokedexViewBoxes.svelte b/src/lib/components/pokedex/PokedexViewBoxes.svelte index 96f101a..624c0ac 100644 --- a/src/lib/components/pokedex/PokedexViewBoxes.svelte +++ b/src/lib/components/pokedex/PokedexViewBoxes.svelte @@ -18,6 +18,7 @@ export let markBoxAsInHome = (boxNumber: number) => {}; export let markBoxAsNotInHome = (boxNumber: number) => {}; export let createCatchRecords = () => {}; + export let onPokemonClick: (pokemon: CombinedData) => void = () => {}; function cellBackgroundColourClass(catchRecord: CatchRecord | null) { if (catchRecord?.caught) { @@ -51,19 +52,19 @@ {#each boxNumbers as boxNumber}

Box {boxNumber}

- - - - -
@@ -72,10 +73,13 @@ ? pokedexEntry.boxPlacementForms : pokedexEntry.boxPlacement} {#if placement.box === boxNumber} -
onPokemonClick({ pokedexEntry, catchRecord })} + aria-label="View details for {pokedexEntry.pokemon}" >
@@ -106,7 +110,7 @@
-
+ {/if} {/each}
diff --git a/src/lib/components/pokedex/PokedexViewList.svelte b/src/lib/components/pokedex/PokedexViewList.svelte deleted file mode 100644 index 3189c57..0000000 --- a/src/lib/components/pokedex/PokedexViewList.svelte +++ /dev/null @@ -1,55 +0,0 @@ - - -
-
- {#if combinedData && combinedData.length > 0} - {#each combinedData as { pokedexEntry, catchRecord }} - - {/each} - {:else if failedToLoad} - {#if creatingRecords && totalRecordsCreated > 0} -

Processed {totalRecordsCreated} Pokédex entries so far...

-

Please be patient, this may take some time.

- {:else if creatingRecords} -

Processing...

-

Please be patient, this may take some time.

- {:else} -

Failed to load

-

- If you're seeing this, you probably haven't created your Pokédex data yet. Please do so by - clicking this button. -

- - {/if} - {:else} -
-

Loading Pokédex

- -
- {/if} -
-
diff --git a/src/lib/models/PokedexEntry.ts b/src/lib/models/PokedexEntry.ts index d502928..91d968b 100644 --- a/src/lib/models/PokedexEntry.ts +++ b/src/lib/models/PokedexEntry.ts @@ -12,23 +12,7 @@ export interface PokedexEntry { regionToEvolveIn: string; evolutionInformation: string; catchInformation: string[]; - // Regional dex numbers - kantoDexNumber?: number; - johtoDexNumber?: number; - hoennDexNumber?: number; - sinnohDexNumber?: number; - unovaBwDexNumber?: number; - unovaB2w2DexNumber?: number; - kalosCentralDexNumber?: number; - kalosCoastalDexNumber?: number; - kalosMountainDexNumber?: number; - alolaSmDexNumber?: number; - alolaUsumDexNumber?: number; - galarDexNumber?: number; - galarIsleOfArmorDexNumber?: number; - galarCrownTundraDexNumber?: number; - hisuiDexNumber?: number; - paldeaDexNumber?: number; + // Note: Regional dex numbers stored in separate regional_dex_numbers table } // Database record type for Supabase @@ -43,23 +27,7 @@ export interface PokedexEntryDB { regionToEvolveIn: string | null; evolutionInformation: string | null; catchInformation: string[] | null; - // Regional dex numbers - snake_case to match database - kanto_dex_number: number | null; - johto_dex_number: number | null; - hoenn_dex_number: number | null; - sinnoh_dex_number: number | null; - unova_bw_dex_number: number | null; - unova_b2w2_dex_number: number | null; - kalos_central_dex_number: number | null; - kalos_coastal_dex_number: number | null; - kalos_mountain_dex_number: number | null; - alola_sm_dex_number: number | null; - alola_usum_dex_number: number | null; - galar_dex_number: number | null; - galar_isle_of_armor_dex_number: number | null; - galar_crown_tundra_dex_number: number | null; - hisui_dex_number: number | null; - paldea_dex_number: number | null; + // Note: Regional dex numbers stored in separate regional_dex_numbers table createdAt: string; updatedAt: string; } diff --git a/src/lib/repositories/CombinedDataRepository.ts b/src/lib/repositories/CombinedDataRepository.ts index cd1868d..b1c3088 100644 --- a/src/lib/repositories/CombinedDataRepository.ts +++ b/src/lib/repositories/CombinedDataRepository.ts @@ -2,8 +2,6 @@ import { type PokedexEntry, type PokedexEntryDB } from '$lib/models/PokedexEntry import { type CatchRecord, type CatchRecordDB } from '$lib/models/CatchRecord'; import { type CombinedData } from '$lib/models/CombinedData'; import type { SupabaseClient } from '@supabase/supabase-js'; -import { getRegionalDexColumnName } from '$lib/utils/regionalDexMapping'; -import { calculateBoxPlacement } from '$lib/utils/boxPlacement'; class CombinedDataRepository { constructor( @@ -27,23 +25,8 @@ class CombinedDataRepository { catchInformation: entry.catchInformation || [], // Box placement will be calculated dynamically after sorting boxPlacementForms: { box: 0, row: 0, column: 0 }, - boxPlacement: { box: 0, row: 0, column: 0 }, - kantoDexNumber: entry.kanto_dex_number ?? undefined, - johtoDexNumber: entry.johto_dex_number ?? undefined, - hoennDexNumber: entry.hoenn_dex_number ?? undefined, - sinnohDexNumber: entry.sinnoh_dex_number ?? undefined, - unovaBwDexNumber: entry.unova_bw_dex_number ?? undefined, - unovaB2w2DexNumber: entry.unova_b2w2_dex_number ?? undefined, - kalosCentralDexNumber: entry.kalos_central_dex_number ?? undefined, - kalosCoastalDexNumber: entry.kalos_coastal_dex_number ?? undefined, - kalosMountainDexNumber: entry.kalos_mountain_dex_number ?? undefined, - alolaSmDexNumber: entry.alola_sm_dex_number ?? undefined, - alolaUsumDexNumber: entry.alola_usum_dex_number ?? undefined, - galarDexNumber: entry.galar_dex_number ?? undefined, - galarIsleOfArmorDexNumber: entry.galar_isle_of_armor_dex_number ?? undefined, - galarCrownTundraDexNumber: entry.galar_crown_tundra_dex_number ?? undefined, - hisuiDexNumber: entry.hisui_dex_number ?? undefined, - paldeaDexNumber: entry.paldea_dex_number ?? undefined + boxPlacement: { box: 0, row: 0, column: 0 } + // Note: Regional dex numbers are stored in separate regional_dex_numbers table }; } @@ -71,8 +54,8 @@ class CombinedDataRepository { // Apply filters if (!enableForms) { - // Filter to only base forms (form is NULL) - query = query.is('form', null); + // Filter to only base forms (form is NULL) OR Unown "A" (since Unown has no base form) + query = query.or('form.is.null,and(pokemon.eq.Unown,form.eq.A)'); } if (region) { @@ -83,22 +66,9 @@ class CombinedDataRepository { query = query.contains('gamesToCatchIn', [game]); } - // Determine ordering strategy based on game filter - if (game) { - const regionalColumn = getRegionalDexColumnName(game); - if (regionalColumn) { - // Order by regional dex with national dex fallback for NULLs - query = query - .order(regionalColumn, { ascending: true, nullsFirst: false }) - .order('pokedexNumber', { ascending: true }); - } else { - // Game specified but has no regional dex mapping - query = query.order('pokedexNumber', { ascending: true }); - } - } else { - // No game filter - order by national dex number - query = query.order('pokedexNumber', { ascending: true }); - } + // Always order by national dex number + // Note: Regional dex ordering would require joining with regional_dex_numbers table + query = query.order('pokedexNumber', { ascending: true }); const { data: entries, error: entriesError } = await query; @@ -162,8 +132,8 @@ class CombinedDataRepository { // Apply filters if (!enableForms) { - // Filter to only base forms (form is NULL) - query = query.is('form', null); + // Filter to only base forms (form is NULL) OR Unown "A" (since Unown has no base form) + query = query.or('form.is.null,and(pokemon.eq.Unown,form.eq.A)'); } if (region) { @@ -174,22 +144,9 @@ class CombinedDataRepository { query = query.contains('gamesToCatchIn', [game]); } - // Determine ordering strategy based on game filter - if (game) { - const regionalColumn = getRegionalDexColumnName(game); - if (regionalColumn) { - // Order by regional dex with national dex fallback for NULLs - query = query - .order(regionalColumn, { ascending: true, nullsFirst: false }) - .order('pokedexNumber', { ascending: true }); - } else { - // Game specified but has no regional dex mapping - query = query.order('pokedexNumber', { ascending: true }); - } - } else { - // No game filter - order by national dex number - query = query.order('pokedexNumber', { ascending: true }); - } + // Always order by national dex number + // Note: Regional dex ordering would require joining with regional_dex_numbers table + query = query.order('pokedexNumber', { ascending: true }); const { data: entries, error: entriesError } = await query; @@ -247,8 +204,8 @@ class CombinedDataRepository { // Apply same filters as in findCombinedData if (!enableForms) { - // Filter to only base forms (form is NULL) - query = query.is('form', null); + // Filter to only base forms (form is NULL) OR Unown "A" (since Unown has no base form) + query = query.or('form.is.null,and(pokemon.eq.Unown,form.eq.A)'); } if (region) { diff --git a/src/routes/api/games/+server.ts b/src/routes/api/games/+server.ts new file mode 100644 index 0000000..104302b --- /dev/null +++ b/src/routes/api/games/+server.ts @@ -0,0 +1,32 @@ +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 }); + } +}; diff --git a/src/routes/pokedex/[id]/+page.svelte b/src/routes/pokedex/[id]/+page.svelte index 9d6fc58..8c0f3d6 100644 --- a/src/routes/pokedex/[id]/+page.svelte +++ b/src/routes/pokedex/[id]/+page.svelte @@ -5,9 +5,9 @@ import { type CombinedData } from '$lib/models/CombinedData'; import { browser } from '$app/environment'; import type { PokedexEntry } from '$lib/models/PokedexEntry'; - import PokedexSidebar from '$lib/components/pokedex/PokedexSidebar.svelte'; - import PokedexViewList from '$lib/components/pokedex/PokedexViewList.svelte'; import PokedexViewBoxes from '$lib/components/pokedex/PokedexViewBoxes.svelte'; + import PokedexModal from '$lib/components/pokedex/PokedexModal.svelte'; + import PokedexEntryCatchRecord from '$lib/components/pokedex/PokedexEntryCatchRecord.svelte'; import type { PageData } from './$types'; export let data: PageData; @@ -23,40 +23,49 @@ let creatingRecords = false; let totalRecordsCreated = 0; let failedToLoad = false; - let catchRegion = ''; - let catchGame = ''; let localUser: User | null; - let showOrigins = true; - let showShiny = false; - let drawerOpen = false; - let viewAsBoxes = false; let boxNumbers: number[] = []; + let showModal = false; + let selectedPokemon: CombinedData | null = null; + + // Derive from pokedex config + $: showOrigins = pokedex.isOriginDex; + $: showShiny = pokedex.isShinyDex; const unsubscribe = user.subscribe((value) => { localUser = value; }); onDestroy(unsubscribe); - function toggleOrigins() { - showOrigins = !showOrigins; + function openPokemonModal(pokemon: CombinedData) { + selectedPokemon = pokemon; + showModal = true; } - async function toggleShiny() { - showShiny = !showShiny; - await getData(); + function closePokemonModal() { + showModal = false; + selectedPokemon = null; } - async function toggleViewAsBoxes() { - viewAsBoxes = !viewAsBoxes; - await getData(); + async function handleModalCatchUpdate(event: any) { + await updateACatch(event); // Existing handler + // Sync modal with refreshed data + if (selectedPokemon && combinedData) { + const updated = combinedData.find( + (cd) => cd.pokedexEntry._id === selectedPokemon!.pokedexEntry._id + ); + if (updated) { + selectedPokemon = updated; + } + } } async function getData(setCombinedDataToNull = true) { if (setCombinedDataToNull) { combinedData = null; } - // Use new pokédex-scoped endpoint - let endpoint = `/api/pokedexes/${pokedexId}/combined-data?page=${currentPage}&limit=${viewAsBoxes ? 9999 : itemsPerPage}&enableForms=${pokedex.isFormDex}®ion=${catchRegion}&game=${catchGame}`; + // Use new pokédex-scoped endpoint - always fetch all data for box view + let endpoint = `/api/pokedexes/${pokedexId}/combined-data?page=${currentPage}&limit=9999&enableForms=${pokedex.isFormDex}`; const response = await fetch(endpoint); const fetchedData = await response.json(); @@ -66,7 +75,8 @@ } combinedData = fetchedData.combinedData; totalPages = fetchedData.totalPages || 0; - if (viewAsBoxes) { + // Always extract box numbers for box view + if (combinedData) { boxNumbers = [ ...new Set( combinedData.map(({ pokedexEntry }) => @@ -116,6 +126,8 @@ needsToEvolve: boolean, inHome: boolean | null = null ) { + if (!combinedData) return; + let catchRecordsToUpdate = combinedData .filter(({ pokedexEntry }) => (pokedex.isFormDex ? pokedexEntry.boxPlacementForms.box : pokedexEntry.boxPlacement.box) === @@ -260,63 +272,119 @@ {#if !localUser}

Please sign in

{:else} -
- -
- +
+ +
+
+
+ +
+

{pokedex.name}

- {#if viewAsBoxes} - - {:else} - - {/if} -
-
- - +
+ + {#if pokedex.isLivingDex} +
+ + + + Living +
+ {/if} + {#if pokedex.isShinyDex} +
+ + + + Shiny +
+ {/if} + {#if pokedex.isOriginDex} +
+ + + + Origin +
+ {/if} + {#if pokedex.isFormDex} +
+ + + + Form +
+ {/if} + + + {#if pokedex.gameScope} +
+
+ + + + + {pokedex.gameScope} +
+ {:else} +
+
+ + + + All Games +
+ {/if} +
+ + {#if pokedex.description} +

{pokedex.description}

+ {/if} +
+ + + +
+
+ + +
+ + {#if showModal && selectedPokemon} + + + + {/if} {/if} diff --git a/supabase/migrations/20260105151500_create_games_table.sql b/supabase/migrations/20260105151500_create_games_table.sql new file mode 100644 index 0000000..56619e1 --- /dev/null +++ b/supabase/migrations/20260105151500_create_games_table.sql @@ -0,0 +1,40 @@ +-- Create games table to store game metadata +CREATE TABLE IF NOT EXISTS games ( + id TEXT PRIMARY KEY, + "displayName" TEXT NOT NULL, + region TEXT NOT NULL, + generation INTEGER NOT NULL, + "releaseYear" INTEGER NOT NULL, + "createdAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + "updatedAt" TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +-- Enable RLS +ALTER TABLE games ENABLE ROW LEVEL SECURITY; + +-- Allow anyone to read games (public reference data) +CREATE POLICY "Games are publicly readable" + ON games + FOR SELECT + TO public + USING (true); + +-- Insert games data from games.csv +INSERT INTO games (id, "displayName", region, generation, "releaseYear") VALUES + ('red', 'Red', 'Kanto', 1, 1996), + ('blue', 'Blue', 'Kanto', 1, 1996), + ('yellow', 'Yellow', 'Kanto', 1, 1998), + ('lg--pikachu', 'LG: Pikachu', 'Kanto', 7, 2018), + ('lg--eevee', 'LG: Eevee', 'Kanto', 7, 2018), + ('gold', 'Gold', 'Johto', 2, 1999), + ('silver', 'Silver', 'Johto', 2, 1999), + ('crystal', 'Crystal', 'Johto', 2, 2000), + ('heartgold', 'HeartGold', 'Johto', 4, 2009), + ('soulsilver', 'SoulSilver', 'Johto', 4, 2009), + ('legends-arceus', 'Legends: Arceus', 'Hisui', 8, 2022) +ON CONFLICT (id) DO UPDATE SET + "displayName" = EXCLUDED."displayName", + region = EXCLUDED.region, + generation = EXCLUDED.generation, + "releaseYear" = EXCLUDED."releaseYear", + "updatedAt" = NOW(); diff --git a/supabase/migrations/20260104000003_seed_kanto.sql b/supabase/migrations/20260105155340_seed_kanto.sql similarity index 90% rename from supabase/migrations/20260104000003_seed_kanto.sql rename to supabase/migrations/20260105155340_seed_kanto.sql index 2e60ab6..88960ee 100644 --- a/supabase/migrations/20260104000003_seed_kanto.sql +++ b/supabase/migrations/20260105155340_seed_kanto.sql @@ -33,9 +33,9 @@ INSERT INTO pokedex_entries ( (11, 'Metapod', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (12, 'Butterfree', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (12, 'Butterfree', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(13, 'Weedle', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'LG: Pikachu', 'LG: Eevee']), -(14, 'Kakuna', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'LG: Pikachu', 'LG: Eevee']), -(15, 'Beedrill', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'LG: Pikachu', 'LG: Eevee']), +(13, 'Weedle', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(14, 'Kakuna', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(15, 'Beedrill', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (16, 'Pidgey', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (17, 'Pidgeotto', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (18, 'Pidgeot', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), @@ -45,14 +45,14 @@ INSERT INTO pokedex_entries ( (20, 'Raticate', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (21, 'Spearow', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (22, 'Fearow', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(23, 'Ekans', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'LG: Eevee']), -(24, 'Arbok', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'LG: Eevee']), +(23, 'Ekans', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(24, 'Arbok', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (25, 'Pikachu', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (25, 'Pikachu', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (26, 'Raichu', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (26, 'Raichu', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(27, 'Sandshrew', NULL, false, 'Kanto', ARRAY['Blue', 'Yellow', 'LG: Pikachu']), -(28, 'Sandslash', NULL, false, 'Kanto', ARRAY['Blue', 'Yellow', 'LG: Pikachu']), +(27, 'Sandshrew', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(28, 'Sandslash', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (29, 'Nidoran♀', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (30, 'Nidorina', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (31, 'Nidoqueen', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), @@ -61,33 +61,33 @@ INSERT INTO pokedex_entries ( (34, 'Nidoking', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (35, 'Clefairy', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (36, 'Clefable', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(37, 'Vulpix', NULL, false, 'Kanto', ARRAY['Blue', 'Yellow', 'LG: Eevee']), -(38, 'Ninetales', NULL, false, 'Kanto', ARRAY['Blue', 'Yellow', 'LG: Eevee']), +(37, 'Vulpix', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(38, 'Ninetales', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (39, 'Jigglypuff', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (40, 'Wigglytuff', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (41, 'Zubat', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (41, 'Zubat', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (42, 'Golbat', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (42, 'Golbat', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(43, 'Oddish', NULL, false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(44, 'Gloom', NULL, false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(44, 'Gloom', 'Female', false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(45, 'Vileplume', NULL, false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(45, 'Vileplume', 'Female', false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), +(43, 'Oddish', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(44, 'Gloom', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(44, 'Gloom', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(45, 'Vileplume', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(45, 'Vileplume', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (46, 'Paras', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (47, 'Parasect', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (48, 'Venonat', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (49, 'Venomoth', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (50, 'Diglett', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (51, 'Dugtrio', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(52, 'Meowth', NULL, false, 'Kanto', ARRAY['Blue', 'LG: Eevee']), -(53, 'Persian', NULL, false, 'Kanto', ARRAY['Blue', 'LG: Eevee']), +(52, 'Meowth', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(53, 'Persian', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (54, 'Psyduck', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (55, 'Golduck', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(56, 'Mankey', NULL, false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(57, 'Primeape', NULL, false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(58, 'Growlithe', NULL, false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(59, 'Arcanine', NULL, false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(56, 'Mankey', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(57, 'Primeape', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(58, 'Growlithe', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(59, 'Arcanine', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (60, 'Poliwag', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (61, 'Poliwhirl', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (62, 'Poliwrath', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), @@ -99,9 +99,9 @@ INSERT INTO pokedex_entries ( (66, 'Machop', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (67, 'Machoke', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (68, 'Machamp', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(69, 'Bellsprout', NULL, false, 'Kanto', ARRAY['Blue', 'Yellow', 'LG: Eevee']), -(70, 'Weepinbell', NULL, false, 'Kanto', ARRAY['Blue', 'Yellow', 'LG: Eevee']), -(71, 'Victreebel', NULL, false, 'Kanto', ARRAY['Blue', 'Yellow', 'LG: Eevee']), +(69, 'Bellsprout', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(70, 'Weepinbell', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(71, 'Victreebel', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (72, 'Tentacool', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (73, 'Tentacruel', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (74, 'Geodude', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), @@ -120,8 +120,8 @@ INSERT INTO pokedex_entries ( (85, 'Dodrio', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (86, 'Seel', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (87, 'Dewgong', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(88, 'Grimer', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu']), -(89, 'Muk', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu']), +(88, 'Grimer', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(89, 'Muk', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (90, 'Shellder', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (91, 'Cloyster', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (92, 'Gastly', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), @@ -142,8 +142,8 @@ INSERT INTO pokedex_entries ( (106, 'Hitmonlee', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (107, 'Hitmonchan', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (108, 'Lickitung', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(109, 'Koffing', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'LG: Eevee']), -(110, 'Weezing', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'LG: Eevee']), +(109, 'Koffing', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(110, 'Weezing', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (111, 'Rhyhorn', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (111, 'Rhyhorn', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (112, 'Rhydon', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), @@ -160,12 +160,12 @@ INSERT INTO pokedex_entries ( (120, 'Staryu', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (121, 'Starmie', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (122, 'Mr. Mime', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), -(123, 'Scyther', NULL, false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(123, 'Scyther', 'Female', false, 'Kanto', ARRAY['Red', 'Yellow', 'LG: Pikachu']), -(124, 'Jynx', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'LG: Pikachu', 'LG: Eevee']), -(125, 'Electabuzz', NULL, false, 'Kanto', ARRAY['Red', 'LG: Pikachu', 'LG: Eevee']), -(126, 'Magmar', NULL, false, 'Kanto', ARRAY['Blue', 'LG: Pikachu', 'LG: Eevee']), -(127, 'Pinsir', NULL, false, 'Kanto', ARRAY['Blue', 'Yellow', 'LG: Eevee']), +(123, 'Scyther', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(123, 'Scyther', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(124, 'Jynx', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(125, 'Electabuzz', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(126, 'Magmar', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), +(127, 'Pinsir', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (128, 'Tauros', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (129, 'Magikarp', NULL, false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), (129, 'Magikarp', 'Female', false, 'Kanto', ARRAY['Red', 'Blue', 'Yellow', 'LG: Pikachu', 'LG: Eevee']), diff --git a/supabase/migrations/20260105160807_seed_johto.sql b/supabase/migrations/20260105160807_seed_johto.sql new file mode 100644 index 0000000..79df3ef --- /dev/null +++ b/supabase/migrations/20260105160807_seed_johto.sql @@ -0,0 +1,282 @@ +-- Seed Johto region Pokémon (Gen 2) +-- Auto-generated from CSV files + +-- Insert Johto region-game mappings +INSERT INTO region_game_mappings (region, game) VALUES + ('Johto', 'Gold'), + ('Johto', 'Silver'), + ('Johto', 'Crystal'), + ('Johto', 'HeartGold'), + ('Johto', 'SoulSilver') +ON CONFLICT (region, game) DO NOTHING; + +-- Insert Johto Pokémon entries +INSERT INTO pokedex_entries ( + "pokedexNumber", + pokemon, + form, + "canGigantamax", + "regionToCatchIn", + "gamesToCatchIn" +) VALUES +(152, 'Chikorita', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(153, 'Bayleef', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(154, 'Meganium', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(154, 'Meganium', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(155, 'Cyndaquil', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(156, 'Quilava', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(157, 'Typhlosion', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(158, 'Totodile', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(159, 'Croconaw', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(160, 'Feraligatr', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(161, 'Sentret', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(162, 'Furret', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(163, 'Hoothoot', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(164, 'Noctowl', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(165, 'Ledyba', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(165, 'Ledyba', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(166, 'Ledian', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(166, 'Ledian', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(167, 'Spinarak', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(168, 'Ariados', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(169, 'Crobat', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(170, 'Chinchou', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(171, 'Lanturn', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(172, 'Pichu', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(173, 'Cleffa', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(174, 'Igglybuff', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(175, 'Togepi', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(176, 'Togetic', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(177, 'Natu', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(178, 'Xatu', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(178, 'Xatu', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(179, 'Mareep', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(180, 'Flaaffy', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(181, 'Ampharos', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(182, 'Bellossom', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(183, 'Marill', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(184, 'Azumarill', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(185, 'Sudowoodo', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(185, 'Sudowoodo', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(186, 'Politoed', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(186, 'Politoed', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(187, 'Hoppip', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(188, 'Skiploom', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(189, 'Jumpluff', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(190, 'Aipom', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(190, 'Aipom', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(191, 'Sunkern', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(192, 'Sunflora', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(193, 'Yanma', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(194, 'Wooper', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(194, 'Wooper', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(195, 'Quagsire', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(195, 'Quagsire', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(196, 'Espeon', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(197, 'Umbreon', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(198, 'Murkrow', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(198, 'Murkrow', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(199, 'Slowking', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(200, 'Misdreavus', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'A', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'B', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'C', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'D', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'E', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'F', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'G', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'H', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'I', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'J', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'K', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'L', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'M', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'N', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'O', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'P', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'Q', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'R', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'S', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'T', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'U', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'V', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'W', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'X', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'Y', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', 'Z', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', '!', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(201, 'Unown', '?', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(202, 'Wobbuffet', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(202, 'Wobbuffet', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(203, 'Girafarig', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(203, 'Girafarig', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(204, 'Pineco', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(205, 'Forretress', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(206, 'Dunsparce', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(207, 'Gligar', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(207, 'Gligar', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(208, 'Steelix', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(208, 'Steelix', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(209, 'Snubbull', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(210, 'Granbull', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(211, 'Qwilfish', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(212, 'Scizor', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(212, 'Scizor', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(213, 'Shuckle', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(214, 'Heracross', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(214, 'Heracross', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(215, 'Sneasel', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(215, 'Sneasel', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(216, 'Teddiursa', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(217, 'Ursaring', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(217, 'Ursaring', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(218, 'Slugma', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(219, 'Magcargo', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(220, 'Swinub', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(221, 'Piloswine', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(221, 'Piloswine', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(222, 'Corsola', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(223, 'Remoraid', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(224, 'Octillery', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(224, 'Octillery', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(225, 'Delibird', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(226, 'Mantine', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(227, 'Skarmory', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(228, 'Houndour', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(229, 'Houndoom', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(229, 'Houndoom', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(230, 'Kingdra', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(231, 'Phanpy', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(232, 'Donphan', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(232, 'Donphan', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(234, 'Stantler', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(235, 'Smeargle', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(236, 'Tyrogue', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(237, 'Hitmontop', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(238, 'Smoochum', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(239, 'Elekid', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(240, 'Magby', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(241, 'Miltank', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(242, 'Blissey', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(243, 'Raikou', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(244, 'Entei', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(245, 'Suicune', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(246, 'Larvitar', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(247, 'Pupitar', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(248, 'Tyranitar', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(249, 'Lugia', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(250, 'Ho-Oh', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(251, 'Celebi', NULL, false, 'Johto', ARRAY['Crystal', 'HeartGold', 'SoulSilver']) +ON CONFLICT ON CONSTRAINT unique_pokemon_form DO NOTHING; + +-- Insert Johto regional dex numbers +INSERT INTO regional_dex_numbers ( + pokedex_entry_id, + region, + dex_number +) VALUES + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 152 AND form IS NULL), 'Johto', 1), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 153 AND form IS NULL), 'Johto', 2), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 154 AND form IS NULL), 'Johto', 3), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 155 AND form IS NULL), 'Johto', 4), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 156 AND form IS NULL), 'Johto', 5), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 157 AND form IS NULL), 'Johto', 6), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 158 AND form IS NULL), 'Johto', 7), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 159 AND form IS NULL), 'Johto', 8), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 160 AND form IS NULL), 'Johto', 9), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 161 AND form IS NULL), 'Johto', 10), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 162 AND form IS NULL), 'Johto', 11), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 163 AND form IS NULL), 'Johto', 12), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 164 AND form IS NULL), 'Johto', 13), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 165 AND form IS NULL), 'Johto', 14), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 166 AND form IS NULL), 'Johto', 15), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 167 AND form IS NULL), 'Johto', 16), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 168 AND form IS NULL), 'Johto', 17), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 169 AND form IS NULL), 'Johto', 18), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 170 AND form IS NULL), 'Johto', 19), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 171 AND form IS NULL), 'Johto', 20), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 172 AND form IS NULL), 'Johto', 21), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 173 AND form IS NULL), 'Johto', 22), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 174 AND form IS NULL), 'Johto', 23), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 175 AND form IS NULL), 'Johto', 24), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 176 AND form IS NULL), 'Johto', 25), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 177 AND form IS NULL), 'Johto', 26), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 178 AND form IS NULL), 'Johto', 27), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 179 AND form IS NULL), 'Johto', 28), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 180 AND form IS NULL), 'Johto', 29), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 181 AND form IS NULL), 'Johto', 30), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 182 AND form IS NULL), 'Johto', 31), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 183 AND form IS NULL), 'Johto', 32), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 184 AND form IS NULL), 'Johto', 33), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 185 AND form IS NULL), 'Johto', 34), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 186 AND form IS NULL), 'Johto', 35), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 187 AND form IS NULL), 'Johto', 36), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 188 AND form IS NULL), 'Johto', 37), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 189 AND form IS NULL), 'Johto', 38), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 190 AND form IS NULL), 'Johto', 39), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 191 AND form IS NULL), 'Johto', 40), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 192 AND form IS NULL), 'Johto', 41), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 193 AND form IS NULL), 'Johto', 42), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 194 AND form IS NULL), 'Johto', 43), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 195 AND form IS NULL), 'Johto', 44), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 196 AND form IS NULL), 'Johto', 45), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 197 AND form IS NULL), 'Johto', 46), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 198 AND form IS NULL), 'Johto', 47), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 199 AND form IS NULL), 'Johto', 48), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 200 AND form IS NULL), 'Johto', 49), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 201 AND form = 'A'), 'Johto', 50), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 202 AND form IS NULL), 'Johto', 51), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 203 AND form IS NULL), 'Johto', 52), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 204 AND form IS NULL), 'Johto', 53), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 205 AND form IS NULL), 'Johto', 54), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 206 AND form IS NULL), 'Johto', 55), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 207 AND form IS NULL), 'Johto', 56), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 208 AND form IS NULL), 'Johto', 57), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 209 AND form IS NULL), 'Johto', 58), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 210 AND form IS NULL), 'Johto', 59), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 211 AND form IS NULL), 'Johto', 60), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 212 AND form IS NULL), 'Johto', 61), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 213 AND form IS NULL), 'Johto', 62), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 214 AND form IS NULL), 'Johto', 63), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 215 AND form IS NULL), 'Johto', 64), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 216 AND form IS NULL), 'Johto', 65), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 217 AND form IS NULL), 'Johto', 66), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 218 AND form IS NULL), 'Johto', 67), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 219 AND form IS NULL), 'Johto', 68), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 220 AND form IS NULL), 'Johto', 69), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 221 AND form IS NULL), 'Johto', 70), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 222 AND form IS NULL), 'Johto', 71), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 223 AND form IS NULL), 'Johto', 72), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 224 AND form IS NULL), 'Johto', 73), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 225 AND form IS NULL), 'Johto', 74), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 226 AND form IS NULL), 'Johto', 75), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 227 AND form IS NULL), 'Johto', 76), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 228 AND form IS NULL), 'Johto', 77), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 229 AND form IS NULL), 'Johto', 78), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 230 AND form IS NULL), 'Johto', 79), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 231 AND form IS NULL), 'Johto', 80), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 232 AND form IS NULL), 'Johto', 81), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 234 AND form IS NULL), 'Johto', 83), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 235 AND form IS NULL), 'Johto', 84), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 236 AND form IS NULL), 'Johto', 85), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 237 AND form IS NULL), 'Johto', 86), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 238 AND form IS NULL), 'Johto', 87), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 239 AND form IS NULL), 'Johto', 88), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 240 AND form IS NULL), 'Johto', 89), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 241 AND form IS NULL), 'Johto', 90), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 242 AND form IS NULL), 'Johto', 91), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 243 AND form IS NULL), 'Johto', 92), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 244 AND form IS NULL), 'Johto', 93), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 245 AND form IS NULL), 'Johto', 94), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 246 AND form IS NULL), 'Johto', 95), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 247 AND form IS NULL), 'Johto', 96), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 248 AND form IS NULL), 'Johto', 97), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 249 AND form IS NULL), 'Johto', 98), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 250 AND form IS NULL), 'Johto', 99), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 251 AND form IS NULL), 'Johto', 100); + +-- Add metadata +INSERT INTO metadata (key, value) VALUES + ('johto_seeded', 'true'), + ('johto_seed_date', NOW()::TEXT), + ('johto_pokemon_count', '98'); From 07af29e6e6c285ab41e6a08e3935b6056172c2aa Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Fri, 9 Jan 2026 18:45:47 +0000 Subject: [PATCH 4/4] chore(#67): Address pr comments --- scripts/sql-to-csv.js | 87 ----- .../pokedex/PokedexViewBoxes.svelte | 19 +- src/lib/models/PokedexEntry.ts | 2 - .../repositories/CombinedDataRepository.ts | 48 +-- .../repositories/PokedexEntryRepository.ts | 21 +- src/routes/api/seed/+server.ts | 99 ----- src/routes/auth/confirm/+server.ts | 2 +- src/routes/my-pokedexes/+page.svelte | 24 +- src/routes/pokedex/[id]/+page.svelte | 202 +++++++--- src/routes/welcome/+page.svelte | 365 ++++++++++++++++++ .../migrations/20260105160807_seed_johto.sql | 4 +- 11 files changed, 538 insertions(+), 335 deletions(-) delete mode 100644 scripts/sql-to-csv.js delete mode 100644 src/routes/api/seed/+server.ts create mode 100644 src/routes/welcome/+page.svelte diff --git a/scripts/sql-to-csv.js b/scripts/sql-to-csv.js deleted file mode 100644 index b28d67f..0000000 --- a/scripts/sql-to-csv.js +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env node - -/** - * Converts Kanto seed SQL migration to CSV format - * Parses 20260104000001_seed_kanto.sql and generates: - * - data/pokemon/gen1-kanto.csv - * - data/pokemon/games.csv - */ - -import fs from 'fs'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -// Read the SQL migration file -const sqlPath = path.join(__dirname, '..', 'supabase', 'migrations', '20260104000001_seed_kanto.sql'); -const sqlContent = fs.readFileSync(sqlPath, 'utf-8'); - -// Extract games from region_game_mappings section -const gameMatches = [...sqlContent.matchAll(/\('Kanto', '([^']+)'\)/g)]; -const games = gameMatches.map(m => m[1]); - -console.log(`Found ${games.length} Kanto games:`, games); - -// Extract Pokemon entries from INSERT statement -// Match pattern: (number, 'name', form, boolean, 'region', ARRAY[games], ...) -const valuePattern = /\((\d+),\s*'([^']+)',\s*(NULL|'[^']+'),\s*(true|false),\s*'[^']+',\s*ARRAY\[([^\]]+)\][^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,[^,]*,\s*(NULL|\d+)\)/g; - -const pokemon = []; -let match; -while ((match = valuePattern.exec(sqlContent)) !== null) { - const [_, pokedexNumber, name, formRaw, canGigantamax, gamesRaw, regionalNumberRaw] = match; - - // Parse form (NULL or 'Female') - const form = formRaw === 'NULL' ? '' : formRaw.replace(/'/g, ''); - - // Parse games array - extract game names from ARRAY['Red', 'Blue', ...] - const gamesList = gamesRaw.match(/'([^']+)'/g).map(g => g.replace(/'/g, '')); - const gamesStr = gamesList.join('|'); - - // Parse regional number - const regionalNumber = regionalNumberRaw === 'NULL' ? '' : regionalNumberRaw; - - pokemon.push({ - pokedexNumber, - name, - form, - games: gamesStr, - regionalNumber - }); -} - -console.log(`Extracted ${pokemon.length} Pokemon entries`); - -// Generate gen1-kanto.csv -const kantoCSV = [ - 'pokedexNumber,name,form,games,regionalNumber', - ...pokemon.map(p => { - const form = p.form.includes(',') ? `"${p.form}"` : p.form; - const games = p.games.includes(',') ? `"${p.games}"` : p.games; - return `${p.pokedexNumber},${p.name},${form},${games},${p.regionalNumber}`; - }) -].join('\n'); - -const kantoPath = path.join(__dirname, '..', 'data', 'pokemon', 'gen1-kanto.csv'); -fs.writeFileSync(kantoPath, kantoCSV); -console.log(`✓ Created ${kantoPath}`); - -// Generate games.csv -const gamesCSV = [ - 'id,displayName,region,generation', - ...games.map((game, idx) => { - const id = game.toLowerCase().replace(/[^a-z0-9]/g, '-'); - const generation = game.startsWith('LG:') ? 7 : 1; - return `${id},${game},Kanto,${generation}`; - }) -].join('\n'); - -const gamesPath = path.join(__dirname, '..', 'data', 'pokemon', 'games.csv'); -fs.writeFileSync(gamesPath, gamesCSV); -console.log(`✓ Created ${gamesPath}`); - -console.log('\n✅ Conversion complete!'); -console.log(` gen1-kanto.csv: ${pokemon.length} entries`); -console.log(` games.csv: ${games.length} games`); diff --git a/src/lib/components/pokedex/PokedexViewBoxes.svelte b/src/lib/components/pokedex/PokedexViewBoxes.svelte index 624c0ac..f6bb523 100644 --- a/src/lib/components/pokedex/PokedexViewBoxes.svelte +++ b/src/lib/components/pokedex/PokedexViewBoxes.svelte @@ -1,12 +1,11 @@ - {pokedex.name} - Living Dex Tracker + {pokedex ? `${pokedex.name} - Living Dex Tracker` : 'Pokédex - Living Dex Tracker'} {#if !localUser}

Please sign in

+{:else if !pokedex} +

Loading...

{:else}
@@ -285,32 +309,64 @@ {#if pokedex.isLivingDex}
- - + + Living
{/if} {#if pokedex.isShinyDex}
- - + + Shiny
{/if} {#if pokedex.isOriginDex}
- - + + Origin
{/if} {#if pokedex.isFormDex}
- - + + Form
@@ -320,17 +376,35 @@ {#if pokedex.gameScope}
- + - + {pokedex.gameScope}
{:else}
- - + + All Games
@@ -345,8 +419,15 @@
- - + + My Pokédexes @@ -358,7 +439,6 @@ diff --git a/src/routes/welcome/+page.svelte b/src/routes/welcome/+page.svelte new file mode 100644 index 0000000..d0a964f --- /dev/null +++ b/src/routes/welcome/+page.svelte @@ -0,0 +1,365 @@ + + + + Welcome - Living Dex Tracker + + + +
+
+ + {#if showSuccess} +
+
+ + + + Account Created Successfully! +
+
+ {/if} + + +
+
+ +
+

+ Welcome to Living Dex Tracker! +

+ +
+ +
+
+ + + +
+
+

Check Your Email

+

+ We've sent you a magic link to verify your account. Click the link in your email + to sign in and start tracking your Pokédex progress. +

+
+
+ +

+ After clicking the link, you'll be automatically signed in and can start tracking your + Pokémon catches across all generations! +

+ + +
+

+ Haven't received the email? Check your spam or junk + folder. +

+

+ Still having trouble? + + Contact support + for assistance. +

+
+
+
+ + +
+
+

+ + + + What's Next? +

+ +
    +
  • +
    +
    + + + +
    +
    +
    +

    Check your email

    +

    Look for our verification email in your inbox

    +
    +
  • + +
  • +
    +
    + + + +
    +
    +
    +

    Click the magic link

    +

    This will sign you in and verify your account

    +
    +
  • + +
  • +
    +
    + + + +
    +
    +
    +

    Start tracking your Pokémon

    +

    + Create your first Pokédex and begin your journey! +

    +
    +
  • +
+ + +
+
+ + + + The verification link expires in 24 hours +
+
+
+
+
+
+ + +
+

What You Can Do With Living Dex Tracker

+
+
+
+ + + +

Track Multiple Pokédexes

+

+ Manage different Living Dex challenges across all generations +

+
+
+ +
+
+ + + +

Share Your Progress

+

Connect with friends and share your Pokédex journey

+
+
+ +
+
+ + + +

Works Offline

+

Track your catches even without an internet connection

+
+
+
+
+
+
+ + diff --git a/supabase/migrations/20260105160807_seed_johto.sql b/supabase/migrations/20260105160807_seed_johto.sql index 79df3ef..4f32c87 100644 --- a/supabase/migrations/20260105160807_seed_johto.sql +++ b/supabase/migrations/20260105160807_seed_johto.sql @@ -149,6 +149,7 @@ INSERT INTO pokedex_entries ( (231, 'Phanpy', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), (232, 'Donphan', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), (232, 'Donphan', 'Female', false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), +(233, 'Porygon2', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), (234, 'Stantler', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), (235, 'Smeargle', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), (236, 'Tyrogue', NULL, false, 'Johto', ARRAY['Gold', 'Silver', 'Crystal', 'HeartGold', 'SoulSilver']), @@ -256,6 +257,7 @@ INSERT INTO regional_dex_numbers ( ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 230 AND form IS NULL), 'Johto', 79), ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 231 AND form IS NULL), 'Johto', 80), ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 232 AND form IS NULL), 'Johto', 81), + ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 233 AND form IS NULL), 'Johto', 82), ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 234 AND form IS NULL), 'Johto', 83), ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 235 AND form IS NULL), 'Johto', 84), ((SELECT id FROM pokedex_entries WHERE "pokedexNumber" = 236 AND form IS NULL), 'Johto', 85), @@ -279,4 +281,4 @@ INSERT INTO regional_dex_numbers ( INSERT INTO metadata (key, value) VALUES ('johto_seeded', 'true'), ('johto_seed_date', NOW()::TEXT), - ('johto_pokemon_count', '98'); + ('johto_pokemon_count', '99');