Move UI controls to bottom and require authentication for stats

- Moved stats button, auth buttons, and debug info to bottom of main page
- Added authentication requirement for /stats route
- Show login prompt for unauthenticated users accessing stats
- Include AuthModal for sign in/sign up from stats page

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
George Powell
2026-02-05 17:57:29 -05:00
parent 96024d5048
commit b1591229ba
3 changed files with 79 additions and 69 deletions

View File

@@ -453,43 +453,6 @@
<span class="big-text"
>{isDev ? "Dev Edition | " : ""}{currentDate}</span
>
<div class="mt-4 flex flex-col items-center gap-3">
<div class="flex gap-3">
<a
href="/stats?{user ? `userId=${user.id}` : `anonymousId=${anonymousId}`}"
class="inline-flex items-center px-4 py-2 bg-amber-600 text-white rounded-lg hover:bg-amber-700 transition-colors text-sm font-medium shadow-md"
>
📊 View Stats
</a>
{#if user}
<form method="POST" action="/auth/logout" use:enhance>
<button
type="submit"
class="inline-flex items-center px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors text-sm font-medium shadow-md"
>
🚪 Sign Out
</button>
</form>
{:else}
<button
onclick={() => authModalOpen = true}
class="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm font-medium shadow-md"
>
🔐 Sign In
</button>
{/if}
</div>
{#if isDev}
<div class="text-xs text-gray-600 bg-gray-100 px-3 py-2 rounded border">
<div><strong>Debug Info:</strong></div>
<div>User: {user ? `${user.email} (ID: ${user.id})` : 'Not signed in'}</div>
<div>Session: {session ? `Expires ${session.expiresAt.toLocaleDateString()}` : 'No session'}</div>
<div>Anonymous ID: {anonymousId || 'Not set'}</div>
</div>
{/if}
</div>
</div>
<div class="flex flex-col gap-6">
@@ -532,9 +495,44 @@
<Credits />
{/if}
</div>
{#if isDev}
<DevButtons />
{/if}
<div class="mt-8 flex flex-col items-center gap-3">
<div class="flex gap-3">
<a
href="/stats?{user ? `userId=${user.id}` : `anonymousId=${anonymousId}`}"
class="inline-flex items-center px-4 py-2 bg-amber-600 text-white rounded-lg hover:bg-amber-700 transition-colors text-sm font-medium shadow-md"
>
📊 View Stats
</a>
{#if user}
<form method="POST" action="/auth/logout" use:enhance>
<button
type="submit"
class="inline-flex items-center px-4 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 transition-colors text-sm font-medium shadow-md"
>
🚪 Sign Out
</button>
</form>
{:else}
<button
onclick={() => authModalOpen = true}
class="inline-flex items-center px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm font-medium shadow-md"
>
🔐 Sign In
</button>
{/if}
</div>
{#if isDev}
<div class="text-xs text-gray-600 bg-gray-100 px-3 py-2 rounded border">
<div><strong>Debug Info:</strong></div>
<div>User: {user ? `${user.email} (ID: ${user.id})` : 'Not signed in'}</div>
<div>Session: {session ? `Expires ${session.expiresAt.toLocaleDateString()}` : 'No session'}</div>
<div>Anonymous ID: {anonymousId || 'Not set'}</div>
</div>
<DevButtons />
{/if}
</div>
</div>
</div>

View File

@@ -4,13 +4,20 @@ import { eq, desc } from 'drizzle-orm';
import type { PageServerLoad } from './$types';
export const load: PageServerLoad = async ({ url, locals }) => {
const userId = url.searchParams.get('userId');
const anonymousId = url.searchParams.get('anonymousId');
// Check if user is authenticated
if (!locals.user) {
return {
stats: null,
error: null,
user: null,
session: null,
requiresAuth: true
};
}
// Prioritize userId (authenticated user) over anonymousId
const targetId = userId || anonymousId;
const userId = locals.user.id;
if (!targetId) {
if (!userId) {
return {
stats: null,
error: 'No user ID provided',
@@ -24,7 +31,7 @@ export const load: PageServerLoad = async ({ url, locals }) => {
const completions = await db
.select()
.from(dailyCompletions)
.where(eq(dailyCompletions.anonymousId, targetId))
.where(eq(dailyCompletions.anonymousId, userId))
.orderBy(desc(dailyCompletions.date));
if (completions.length === 0) {

View File

@@ -2,6 +2,8 @@
import { browser } from "$app/environment";
import { goto } from "$app/navigation";
import { onMount } from "svelte";
import { enhance } from '$app/forms';
import AuthModal from "$lib/components/AuthModal.svelte";
import {
getGradeColor,
formatDate,
@@ -15,9 +17,11 @@
error?: string;
user?: any;
session?: any;
requiresAuth?: boolean;
}
let { data }: { data: PageData } = $props();
let authModalOpen = $state(false);
let loading = $state(true);
@@ -33,28 +37,6 @@
}
onMount(async () => {
const url = new URL(window.location.href);
const hasUserId = url.searchParams.get('userId');
// If user is authenticated, no need to check for anonymousId
if (data.user || hasUserId) {
loading = false;
return;
}
// For anonymous users, ensure anonymousId is in URL
const anonymousId = getOrCreateAnonymousId();
if (!anonymousId) {
goto("/");
return;
}
if (!url.searchParams.get('anonymousId')) {
url.searchParams.set('anonymousId', anonymousId);
goto(url.pathname + url.search);
return;
}
loading = false;
});
@@ -91,6 +73,27 @@
<div class="inline-block w-8 h-8 border-4 border-amber-600 border-t-transparent rounded-full animate-spin"></div>
<p class="mt-4 text-gray-600">Loading your stats...</p>
</div>
{:else if data.requiresAuth}
<div class="text-center py-12">
<div class="bg-blue-100 border border-blue-300 rounded-lg p-8 max-w-md mx-auto">
<h2 class="text-2xl font-bold text-blue-800 mb-4">Authentication Required</h2>
<p class="text-blue-700 mb-6">You must be logged in to see your stats.</p>
<div class="flex flex-col gap-3">
<button
onclick={() => authModalOpen = true}
class="inline-flex items-center justify-center px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors font-medium"
>
🔐 Sign In / Sign Up
</button>
<a
href="/"
class="inline-flex items-center justify-center px-6 py-3 bg-gray-600 text-white rounded-lg hover:bg-gray-700 transition-colors font-medium"
>
← Back to Game
</a>
</div>
</div>
</div>
{:else if data.error}
<div class="text-center py-12">
<div class="bg-red-100 border border-red-300 rounded-lg p-6 max-w-md mx-auto">
@@ -214,3 +217,5 @@
{/if}
</div>
</div>
<AuthModal bind:isOpen={authModalOpen} anonymousId={""} />