diff --git a/src/lib/components/pokedex/PokedexEntryCatchRecord.svelte b/src/lib/components/pokedex/PokedexEntryCatchRecord.svelte index a991184..e496273 100644 --- a/src/lib/components/pokedex/PokedexEntryCatchRecord.svelte +++ b/src/lib/components/pokedex/PokedexEntryCatchRecord.svelte @@ -38,9 +38,9 @@ value: string | CatchInformationItem ): value is CatchInformationItem => typeof value !== 'string'; - function updateCatchRecord(source: UpdateCatchSource) { + function updateCatchRecord(source: UpdateCatchSource, changes?: Partial) { if (readOnly) return; - dispatch('updateCatch', { pokedexEntry, catchRecord, source }); + dispatch('updateCatch', { pokedexEntry, catchRecord, source, changes }); } function onCaughtChange() { @@ -50,7 +50,10 @@ if (catchRecord.caught) { catchRecord.haveToEvolve = false; } - updateCatchRecord('toggle'); + updateCatchRecord('toggle', { + caught: catchRecord.caught, + haveToEvolve: catchRecord.haveToEvolve + }); } function onNeedsToEvolveChange() { @@ -60,7 +63,10 @@ if (catchRecord.haveToEvolve) { catchRecord.caught = false; } - updateCatchRecord('toggle'); + updateCatchRecord('toggle', { + caught: catchRecord.caught, + haveToEvolve: catchRecord.haveToEvolve + }); } @@ -154,7 +160,7 @@ type="checkbox" bind:checked={catchRecord.inHome} class="checkbox checkbox-primary" - on:change={() => updateCatchRecord('toggle')} + on:change={() => updateCatchRecord('toggle', { inHome: catchRecord?.inHome })} /> @@ -168,7 +174,8 @@ type="checkbox" bind:checked={catchRecord.hasGigantamaxed} class="checkbox checkbox-primary" - on:change={() => updateCatchRecord('toggle')} + on:change={() => + updateCatchRecord('toggle', { hasGigantamaxed: catchRecord?.hasGigantamaxed })} /> diff --git a/src/lib/repositories/CatchRecordRepository.ts b/src/lib/repositories/CatchRecordRepository.ts index 31b2afe..65e3521 100644 --- a/src/lib/repositories/CatchRecordRepository.ts +++ b/src/lib/repositories/CatchRecordRepository.ts @@ -90,19 +90,27 @@ class CatchRecordRepository { 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}`); + const groups = new Map[]>(); + for (const row of dbRows) { + const key = Object.keys(row).sort().join(','); + const group = groups.get(key) ?? []; + group.push(row); + groups.set(key, group); } - - return (result ?? []).map((row) => this.transformCatchRecord(row)); + const saved: CatchRecord[] = []; + for (const group of groups.values()) { + const { data, error } = await this.supabase + .from('catch_records') + .upsert(group, { + onConflict: '"userId","pokedexId","pokemonId"', + defaultToNull: false + }) + .select(); + if (error) throw new Error(`Failed to bulk upsert catch records: ${error.message}`); + saved.push(...(data ?? []).map((row) => this.transformCatchRecord(row))); + } + const byPokemon = new Map(saved.map((row) => [row.pokemonId, row])); + return records.map((row) => byPokemon.get(row.pokemonId)!); } async findById(id: string): Promise {