feat(*): Add support for catch records to My Dex page

This commit is contained in:
Josh Creek
2024-07-12 14:19:44 +01:00
parent 0e8af37309
commit e7f1930eff
6 changed files with 460 additions and 31 deletions
+58
View File
@@ -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();
}
};
+171 -31
View File
@@ -1,49 +1,189 @@
<script lang="ts">
import { onMount } from 'svelte';
import { onMount, onDestroy } from 'svelte';
import { user } from '$lib/stores/user.js';
import { type User } from '@supabase/auth-js';
import mongoose, { Types } from 'mongoose';
import { type PokedexEntry } from '$lib/models/PokedexEntry';
import PokemonSprite from '$lib/components/PokemonSprite.svelte';
import CatchRecordModel, { type CatchRecord } from '$lib/models/CatchRecord';
import { type CombinedData } from '$lib/models/CombinedData';
import PokedexEntryCatchRecord from '$lib/components/pokedex/PokedexEntryCatchRecord.svelte';
let pokemonData = null as PokedexEntry[] | null;
let localUser: User | null;
const unsubscribe = user.subscribe((value) => {
localUser = value;
});
onDestroy(unsubscribe);
let pokedexEntries = null as PokedexEntry[] | null;
let catchRecords = null as CatchRecord[] | null;
let combinedData = null as CombinedData[] | null;
let creatingRecords = false;
let totalRecordsCreated = 0;
async function fetchPokeDexEntries() {
console.log('Fetching updated Pokedex entry data');
const response = await fetch('/api/pokedexentries');
if (!response.ok) {
throw new Error('Failed to fetch Pokémon data');
}
pokemonData = await response.json();
pokedexEntries = await response.json();
}
onMount(async () => {
const cachedData = localStorage.getItem('pokeDexEntries');
if (cachedData) {
// Use cached data
pokemonData = JSON.parse(cachedData);
} else {
await fetchPokeDexEntries();
// Cache data in local storage
localStorage.setItem('pokeDexEntries', JSON.stringify(pokemonData));
async function fetchCatchRecords() {
console.log('Fetching catch record data');
const response = await fetch('/api/catch-records');
if (!response.ok) {
throw new Error('Failed to fetch catch record data');
}
catchRecords = await response.json();
// If there are no catch records, make one for each pokedex entry
if (catchRecords?.length === 0 && localUser?.id) {
creatingRecords = true;
const newCatchRecords = pokedexEntries.map((entry) => ({
userId: localUser?.id,
pokedexEntryId: entry._id,
haveToEvolve: false,
caught: false,
inHome: false,
hasGigantamaxed: false,
personalNotes: ''
}));
const batchSize = 500;
for (let i = 0; i < newCatchRecords.length; i += batchSize) {
const batch = newCatchRecords.slice(i, i + batchSize);
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(batch)
};
try {
const response = await fetch('/api/catch-records', requestOptions);
if (!response.ok) {
throw new Error('Failed to create catch records');
}
const createdRecords = await response.json();
totalRecordsCreated += createdRecords.length;
console.log(`Created ${createdRecords.length} catch records`);
} catch (error) {
console.error('Error creating catch records:', error);
}
}
await fetchCatchRecords();
console.log('Created catch records for each pokedex entry');
creatingRecords = false;
}
}
const fetchLastModifiedDate = async () => {
const response = await fetch('/api/pokedex-metadata');
const { lastModified } = await response.json();
return new Date(lastModified);
};
const cacheData = () => {
localStorage.setItem('pokeDexEntries', JSON.stringify(pokedexEntries));
localStorage.setItem('pokeDexLastUpdated', new Date().toISOString());
};
const checkForUpdates = async () => {
const cachedData = localStorage.getItem('pokeDexEntries');
const cachedDate = localStorage.getItem('pokeDexLastUpdated');
if (cachedData && cachedDate) {
const lastModified = await fetchLastModifiedDate();
const lastUpdated = new Date(cachedDate);
if (lastModified <= lastUpdated) {
pokedexEntries = JSON.parse(cachedData);
return;
}
}
await fetchPokeDexEntries();
cacheData();
};
onMount(async () => {
await checkForUpdates()
.then(async () => {
await fetchCatchRecords();
})
.then(async () => {
combinedData = [];
// Combine pokedex entries with their corresponding catch records
pokedexEntries.forEach((entry) => {
let catchRecord = catchRecords.find((record) => record.pokedexEntryId === entry._id);
if (catchRecord) {
combinedData.push({ pokedexEntry: entry, catchRecord });
}
});
});
});
async function updateACatch(catchRecord: CatchRecord) {
alert('here');
// if (!localUser?.id) {
// alert('User not signed in');
// return;
// }
// const requestOptions = {
// method: 'PUT',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify(catchRecord)
// };
// try {
// const response = await fetch('/api/catch-records', requestOptions);
// if (!response.ok) {
// throw new Error('Failed to update catch record');
// }
// const updatedRecord = await response.json();
// console.log('Updated catch record:', updatedRecord);
// } catch (error) {
// console.error('Error updating catch record:', error);
// }
}
</script>
{#if pokemonData}
{#each pokemonData as pokemon}
<div class="container mx-auto">
{#if combinedData}
<div>
<PokemonSprite
pokedexNumber={pokemon.pokedexNumber.toString().padStart(3, '0')}
form={pokemon.form
.replace(/[^a-zA-Z ]/g, '')
.trim()
.replace(/ /g, '-')}
/>
<p>
{pokemon.pokedexNumber.toString().padStart(3, '0')}
{pokemon.pokemon}
{pokemon.form}
</p>
<button>Toggle Forms</button>
<button>Toggle Origins</button>
</div>
{/each}
{:else}
<span class="loading loading-spinner loading-xl"></span>
{/if}
<!-- <p>
<button on:click={() => updateACatch(catchRecord)}>Save</button>
</p> -->
{#each combinedData as { pokedexEntry, catchRecord }}
<div>
<PokedexEntryCatchRecord
{pokedexEntry}
bind:catchRecord
on:updateCatch={() => updateACatch(catchRecord)}
/>
</div>
{/each}
{:else}
<span class="loading loading-spinner loading-xl"></span>
<h1>Loading Pokédex</h1>
<p>Please be patient, this can take some time on the first load.</p>
{#if totalRecordsCreated > 0}
<p>Processing {totalRecordsCreated}/{pokedexEntries?.length}</p>
{:else if creatingRecords}
<p>Processing...</p>
{/if}
{/if}
</div>