diff --git a/src/backend/services/admin.service.js b/src/backend/services/admin.service.js index 7157d0b..78db10d 100644 --- a/src/backend/services/admin.service.js +++ b/src/backend/services/admin.service.js @@ -127,7 +127,12 @@ export async function getUserStats() { lotwConfirmed: sql`CAST(SUM(CASE WHEN ${qsos.lotwQslRstatus} = 'Y' THEN 1 ELSE 0 END) AS INTEGER)`, dclConfirmed: sql`CAST(SUM(CASE WHEN ${qsos.dclQslRstatus} = 'Y' THEN 1 ELSE 0 END) AS INTEGER)`, totalConfirmed: sql`CAST(SUM(CASE WHEN ${qsos.lotwQslRstatus} = 'Y' OR ${qsos.dclQslRstatus} = 'Y' THEN 1 ELSE 0 END) AS INTEGER)`, - lastSync: sql`MAX(${qsos.createdAt})`, + lastSync: sql`( + SELECT MAX(${syncJobs.completedAt}) + FROM ${syncJobs} + WHERE ${syncJobs.userId} = ${users.id} + AND ${syncJobs.status} = 'completed' + )`.mapWith(Number), createdAt: users.createdAt, }) .from(users) @@ -135,7 +140,11 @@ export async function getUserStats() { .groupBy(users.id) .orderBy(sql`COUNT(${qsos.id}) DESC`); - return stats; + // Convert lastSync timestamps (seconds) to Date objects for JSON serialization + return stats.map(stat => ({ + ...stat, + lastSync: stat.lastSync ? new Date(stat.lastSync * 1000) : null, + })); } /** diff --git a/src/frontend/src/routes/+layout.svelte b/src/frontend/src/routes/+layout.svelte index 21fc742..96a1573 100644 --- a/src/frontend/src/routes/+layout.svelte +++ b/src/frontend/src/routes/+layout.svelte @@ -5,7 +5,11 @@ function handleLogout() { auth.logout(); - goto('/auth/login'); + // Use hard redirect to ensure proper navigation after logout + // goto() may not work properly due to SvelteKit client-side routing + if (browser) { + window.location.href = '/auth/login'; + } } diff --git a/src/frontend/src/routes/settings/+page.svelte b/src/frontend/src/routes/settings/+page.svelte index a666e6d..195d436 100644 --- a/src/frontend/src/routes/settings/+page.svelte +++ b/src/frontend/src/routes/settings/+page.svelte @@ -1,5 +1,6 @@