From a12c7d011a28e9b90f8aea1bc15da0b49817bf2f Mon Sep 17 00:00:00 2001 From: George Powell Date: Fri, 13 Feb 2026 00:36:06 -0500 Subject: [PATCH] added some nice animation details --- src/lib/components/VerseDisplay.svelte | 51 ++++++++-- src/routes/+page.svelte | 123 +++++++++++++++++++------ 2 files changed, 140 insertions(+), 34 deletions(-) diff --git a/src/lib/components/VerseDisplay.svelte b/src/lib/components/VerseDisplay.svelte index 3081d3e..5497b24 100644 --- a/src/lib/components/VerseDisplay.svelte +++ b/src/lib/components/VerseDisplay.svelte @@ -1,4 +1,6 @@ - +
{displayVerseText}
- {#if isWon} -

- {displayReference} -

- {/if} +
+ {#if showReference} +

+ {displayReference} +

+ {/if} +
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 038d438..1d84810 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -13,7 +13,7 @@ import DevButtons from "$lib/components/DevButtons.svelte"; import AuthModal from "$lib/components/AuthModal.svelte"; import { getGrade } from "$lib/utils/game"; - import { enhance } from '$app/forms'; + import { enhance } from "$app/forms"; interface Guess { book: BibleBook; @@ -64,6 +64,7 @@ ); let isWon = $derived(guesses.some((g) => g.book.id === correctBookId)); + let showWinScreen = $state(false); let grade = $derived( isWon ? guesses.length === 1 && chapterCorrect @@ -183,18 +184,25 @@ $effect(() => { if (!browser) return; - const localDate = new Date().toLocaleDateString('en-CA'); - console.log('Date check:', { localDate, verseDate: dailyVerse.date, match: dailyVerse.date === localDate }); + const localDate = new Date().toLocaleDateString("en-CA"); + console.log("Date check:", { + localDate, + verseDate: dailyVerse.date, + match: dailyVerse.date === localDate, + }); if (dailyVerse.date === localDate) return; const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone; - console.log('Fetching timezone-correct verse:', { localDate, timezone }); + console.log("Fetching timezone-correct verse:", { + localDate, + timezone, + }); - fetch('/api/daily-verse', { - method: 'POST', + fetch("/api/daily-verse", { + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, body: JSON.stringify({ date: localDate, @@ -203,30 +211,36 @@ }) .then((res) => res.json()) .then((result) => { - console.log('Received verse data:', result); + console.log("Received verse data:", result); dailyVerse = result.dailyVerse; correctBookId = result.correctBookId; correctBook = result.correctBook; }) - .catch((err) => console.error('Failed to fetch timezone-correct verse:', err)); + .catch((err) => + console.error("Failed to fetch timezone-correct verse:", err), + ); }); // Reload when the user returns to a stale tab on a new calendar day $effect(() => { if (!browser) return; - const loadedDate = new Date().toLocaleDateString('en-CA'); + const loadedDate = new Date().toLocaleDateString("en-CA"); function onVisibilityChange() { if (document.hidden) return; - const now = new Date().toLocaleDateString('en-CA'); + const now = new Date().toLocaleDateString("en-CA"); if (now !== loadedDate) { window.location.reload(); } } - document.addEventListener('visibilitychange', onVisibilityChange); - return () => document.removeEventListener('visibilitychange', onVisibilityChange); + document.addEventListener("visibilitychange", onVisibilityChange); + return () => + document.removeEventListener( + "visibilitychange", + onVisibilityChange, + ); }); // Initialize anonymous ID @@ -366,7 +380,7 @@ async function submitStats() { try { const payload = { - anonymousId: anonymousId, // Already set correctly in $effect above + anonymousId: anonymousId, // Already set correctly in $effect above date: dailyVerse.date, guessCount: guesses.length, }; @@ -405,6 +419,33 @@ submitStats(); }); + // Delay showing win screen until GuessesTable animation completes + $effect(() => { + if (!isWon) { + showWinScreen = false; + return; + } + + // Check if user already won today (page reload case) + const winTrackedKey = `bibdle-win-tracked-${dailyVerse.date}`; + const alreadyWonToday = + browser && localStorage.getItem(winTrackedKey) === "true"; + + if (alreadyWonToday) { + // User already won and is refreshing - show immediately + showWinScreen = true; + } else { + // User just won this session - delay for animation + // Animation timing: last column starts at 1500ms, animation takes 600ms + const animationDelay = 1800; + const timeoutId = setTimeout(() => { + showWinScreen = true; + }, animationDelay); + + return () => clearTimeout(timeoutId); + } + }); + $effect(() => { if (!browser || !isWon) return; const key = `bibdle-win-tracked-${dailyVerse.date}`; @@ -455,7 +496,7 @@ lines.push( `${emojis}${guesses.length === 1 && chapterCorrect ? " ⭐" : ""}`, - siteUrl + siteUrl, ); return lines.join("\n"); @@ -548,7 +589,7 @@
- {:else} + {:else if showWinScreen}
📊 View Stats {#if user} -
+ {/if}
- + {#if isDev} -
+
Debug Info:
-
User: {user ? `${user.email} (ID: ${user.id})` : 'Not signed in'}
-
Session: {session ? `Expires ${session.expiresAt.toLocaleDateString()}` : 'No session'}
-
Anonymous ID: {anonymousId || 'Not set'}
-
Client Local Time: {new Date().toLocaleString('en-US', { timeZone: Intl.DateTimeFormat().resolvedOptions().timeZone, timeZoneName: 'short' })}
-
Client Local Date: {new Date().toLocaleDateString('en-CA')}
+
+ User: {user + ? `${user.email} (ID: ${user.id})` + : "Not signed in"} +
+
+ Session: {session + ? `Expires ${session.expiresAt.toLocaleDateString()}` + : "No session"} +
+
Anonymous ID: {anonymousId || "Not set"}
+
+ Client Local Time: {new Date().toLocaleString("en-US", { + timeZone: + Intl.DateTimeFormat().resolvedOptions() + .timeZone, + timeZoneName: "short", + })} +
+
+ Client Local Date: {new Date().toLocaleDateString( + "en-CA", + )} +
Daily Verse Date: {dailyVerse.date}