mirror of
https://github.com/jcreek/LivingDexTracker.git
synced 2026-07-13 11:03:44 +00:00
feat(#56): Address PR comments
This commit is contained in:
@@ -88,12 +88,29 @@ export const POST = async (event: RequestEvent) => {
|
||||
try {
|
||||
const userId = await requireAuth(event);
|
||||
const { id: pokedexId } = event.params;
|
||||
const records: Partial<CatchRecord>[] = await event.request.json();
|
||||
const body: unknown = await event.request.json();
|
||||
|
||||
if (!pokedexId) {
|
||||
return json({ error: 'Pokedex ID is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
if (!Array.isArray(body)) {
|
||||
return json({ error: 'Request body must be an array of catch records' }, { status: 400 });
|
||||
}
|
||||
const invalidIndex = body.findIndex((r) => {
|
||||
if (!r || typeof r !== 'object') return true;
|
||||
const entryId = (r as Partial<CatchRecord>).pokedexEntryId;
|
||||
return entryId === undefined || entryId === null || entryId === '';
|
||||
});
|
||||
if (invalidIndex !== -1) {
|
||||
return json(
|
||||
{ error: `Record at index ${invalidIndex} is missing required field "pokedexEntryId"` },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const records = body as Array<Partial<CatchRecord> & Pick<CatchRecord, 'pokedexEntryId'>>;
|
||||
|
||||
const { session } = await event.locals.safeGetSession();
|
||||
if (session) {
|
||||
await event.locals.supabase.auth.setSession(session);
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
|
||||
async function readApiErrorMessage(response: Response): Promise<string> {
|
||||
try {
|
||||
const data = await response.json();
|
||||
// Use a clone so we can still fall back to reading the original body as text.
|
||||
const data = await response.clone().json();
|
||||
if (data && typeof data === 'object' && 'error' in data && typeof data.error === 'string') {
|
||||
return data.error;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
|
||||
let catchWriteQueue: ReturnType<typeof createCatchRecordWriteQueue> | null = null;
|
||||
let catchWriteQueueKey: string | null = null;
|
||||
let catchWriteQueueUnsubscribe: (() => void) | null = null;
|
||||
let catchWriteStatus: CatchRecordWriteQueueStatus = {
|
||||
pending: 0,
|
||||
inFlight: 0,
|
||||
@@ -57,6 +58,10 @@
|
||||
localUser = value;
|
||||
});
|
||||
onDestroy(unsubscribe);
|
||||
onDestroy(() => {
|
||||
catchWriteQueueUnsubscribe?.();
|
||||
catchWriteQueueUnsubscribe = null;
|
||||
});
|
||||
|
||||
function openPokemonModal(pokemon: CombinedData) {
|
||||
selectedPokemon = pokemon;
|
||||
@@ -75,15 +80,19 @@
|
||||
const desiredKey = `${localUser.id}:${pokedexId}`;
|
||||
if (catchWriteQueue && catchWriteQueueKey === desiredKey) return;
|
||||
|
||||
// Unsubscribe from the previous queue's status store before replacing the queue.
|
||||
catchWriteQueueUnsubscribe?.();
|
||||
catchWriteQueueUnsubscribe = null;
|
||||
|
||||
catchWriteQueue = createCatchRecordWriteQueue({
|
||||
endpointUrl: `/api/pokedexes/${pokedexId}/catch-records`,
|
||||
fetchFn: fetch,
|
||||
batchSize: 200,
|
||||
concurrency: 2
|
||||
concurrency: 1
|
||||
});
|
||||
catchWriteQueueKey = desiredKey;
|
||||
|
||||
catchWriteQueue.getStatus.subscribe((s) => {
|
||||
catchWriteQueueUnsubscribe = catchWriteQueue.getStatus.subscribe((s) => {
|
||||
catchWriteStatus = s;
|
||||
});
|
||||
}
|
||||
@@ -332,9 +341,11 @@
|
||||
if (document.visibilityState === 'hidden') flushKeepalive();
|
||||
};
|
||||
|
||||
const onOnline = () => void catchWriteQueue?.flushNow();
|
||||
|
||||
window.addEventListener('pagehide', flushKeepalive);
|
||||
document.addEventListener('visibilitychange', onVisibilityChange);
|
||||
window.addEventListener('online', () => void catchWriteQueue?.flushNow());
|
||||
window.addEventListener('online', onOnline);
|
||||
|
||||
// Periodic reconciliation to guard against any missed state (e.g. aborted tab-close flush).
|
||||
const reconcileInterval = window.setInterval(() => {
|
||||
@@ -347,6 +358,7 @@
|
||||
return () => {
|
||||
window.removeEventListener('pagehide', flushKeepalive);
|
||||
document.removeEventListener('visibilitychange', onVisibilityChange);
|
||||
window.removeEventListener('online', onOnline);
|
||||
window.clearInterval(reconcileInterval);
|
||||
};
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user