diff --git a/src/lib/i18n/en.json b/src/lib/i18n/en.json index 8c6b911..e4656c6 100644 --- a/src/lib/i18n/en.json +++ b/src/lib/i18n/en.json @@ -88,6 +88,8 @@ "changePassword": "Change password", "dailyHistoryTitle": "Daily history", "noDailyHistory": "No history available", + "triedCharactersTitle": "Tried characters", + "noTriedCharacters": "No characters recorded", "noImage": "N/A", "trySingular": "try", "tryPlural": "tries", @@ -111,6 +113,8 @@ "reset": "Play again", "description": "Guess the character. Each hint unlocks after a certain number of guesses. Good luck!", "friendsToday": "Your friends today", + "friendsTriedCharacters": "Tried characters", + "friendsNoTriedCharacters": "No characters recorded", "friendTrySingular": "try", "friendTryPlural": "tries" }, diff --git a/src/lib/i18n/fr.json b/src/lib/i18n/fr.json index ac6d574..413a8f5 100644 --- a/src/lib/i18n/fr.json +++ b/src/lib/i18n/fr.json @@ -88,6 +88,8 @@ "changePassword": "Changer le mot de passe", "dailyHistoryTitle": "Historique des Daily", "noDailyHistory": "Aucun historique disponible", + "triedCharactersTitle": "Personnages essayes", + "noTriedCharacters": "Aucun personnage enregistre", "noImage": "N/A", "trySingular": "tentative", "tryPlural": "tentatives", @@ -111,6 +113,8 @@ "reset": "Recommencer", "description": "Devine le personnage. Chaque indice se debloque apres un certain nombre de tentatives. Bonne chance !", "friendsToday": "Tes amis aujourd'hui", + "friendsTriedCharacters": "Personnages essayes", + "friendsNoTriedCharacters": "Aucun personnage enregistre", "friendTrySingular": "coup", "friendTryPlural": "coups" }, diff --git a/src/routes/(game)/daily/+page.server.ts b/src/routes/(game)/daily/+page.server.ts index 26d52b6..766f59a 100644 --- a/src/routes/(game)/daily/+page.server.ts +++ b/src/routes/(game)/daily/+page.server.ts @@ -1,6 +1,6 @@ import { error } from '@sveltejs/kit'; import { db } from '$lib/server/db'; -import { characterHistory, config, friendship, user, userCharacterHistory } from '$lib/server/db/schema'; +import { character, characterHistory, config, friendship, user, userCharacterHistory } from '$lib/server/db/schema'; import { getDailyModeCharacters, getOrCreateTodayCharacter, getYesterdayCharacter, getTodayCharacterWinsCount, getDateKey } from '$lib/server/daily-character'; import { and, eq, inArray, like, or } from 'drizzle-orm'; @@ -17,7 +17,13 @@ export async function load(event) { // Load the win count for today const winCount = await getTodayCharacterWinsCount(dailyCharacter.id); - let friendsTodayResults: Array<{ userId: string; name: string; image: string | null; tryCount: number }> = []; + let friendsTodayResults: Array<{ + userId: string; + name: string; + image: string | null; + tryCount: number; + triedCharacters: Array<{ id: string; name: string; pictureUrl: string | null }>; + }> = []; if (event.locals.user) { const currentUserId = event.locals.user.id; @@ -51,12 +57,13 @@ export async function load(event) { const todayCharacterHistoryId = todayHistoryEntry?.id; if (todayCharacterHistoryId) { - friendsTodayResults = await db + const friendResultsRaw = await db .select({ userId: user.id, name: user.name, image: user.image, - tryCount: userCharacterHistory.tryCount + tryCount: userCharacterHistory.tryCount, + triedCharacterIds: userCharacterHistory.triedCharacterIds }) .from(userCharacterHistory) .innerJoin(user, eq(userCharacterHistory.userId, user.id)) @@ -67,6 +74,33 @@ export async function load(event) { ) ) .orderBy(userCharacterHistory.tryCount); + + const uniqueTriedCharacterIds = Array.from(new Set( + friendResultsRaw.flatMap((entry) => entry.triedCharacterIds ?? []) + )); + + const triedCharacters = uniqueTriedCharacterIds.length > 0 + ? await db + .select({ + id: character.id, + name: character.name, + pictureUrl: character.pictureUrl + }) + .from(character) + .where(inArray(character.id, uniqueTriedCharacterIds)) + : []; + + const triedCharactersById = new Map(triedCharacters.map((entry) => [entry.id, entry])); + + friendsTodayResults = friendResultsRaw.map((entry) => ({ + userId: entry.userId, + name: entry.name, + image: entry.image, + tryCount: entry.tryCount, + triedCharacters: (entry.triedCharacterIds ?? []) + .map((characterId) => triedCharactersById.get(characterId)) + .filter((triedEntry): triedEntry is (typeof triedCharacters)[number] => !!triedEntry) + })); } } } diff --git a/src/routes/(game)/daily/+page.svelte b/src/routes/(game)/daily/+page.svelte index 0f02df7..c0bcce5 100644 --- a/src/routes/(game)/daily/+page.svelte +++ b/src/routes/(game)/daily/+page.svelte @@ -159,6 +159,8 @@ // Check if player won if (character.id === dailyCharacter.id) { + const triedCharacterIds = selectedCharacters.map(selected => selected.id); + // Send request to record win in database fetch('/daily', { method: 'POST', @@ -167,7 +169,8 @@ }, body: JSON.stringify({ characterId: dailyCharacter.id, - tryCount: selectedCharacters.length + tryCount: selectedCharacters.length, + triedCharacterIds }) }).catch(err => console.error('Failed to record win:', err)); @@ -317,8 +320,9 @@

{$t.game.daily.friendsToday}

{#each data.friendsTodayResults as friendResult (friendResult.userId)} -
-
+
+
+
{#if friendResult.image} {/if}

{friendResult.name}

+
+

+ {friendResult.tryCount} {friendResult.tryCount > 1 ? $t.game.daily.friendTryPlural : $t.game.daily.friendTrySingular} +

+
+
+

+ {$t.game.daily.friendsTriedCharacters} +

+ {#if friendResult.triedCharacters && friendResult.triedCharacters.length > 0} +
+ {#each friendResult.triedCharacters as triedCharacter (triedCharacter.id)} + + {#if triedCharacter.pictureUrl} + {triedCharacter.name} + {/if} + {triedCharacter.name} + + {/each} +
+ {:else} +

{$t.game.daily.friendsNoTriedCharacters}

+ {/if}
-

- {friendResult.tryCount} {friendResult.tryCount > 1 ? $t.game.daily.friendTryPlural : $t.game.daily.friendTrySingular} -

{/each}
diff --git a/src/routes/(game)/daily/+server.ts b/src/routes/(game)/daily/+server.ts index d5072ea..511b0e5 100644 --- a/src/routes/(game)/daily/+server.ts +++ b/src/routes/(game)/daily/+server.ts @@ -7,7 +7,10 @@ import { getDateKey } from '$lib/server/daily-character'; export async function POST({ request, locals }) { try { - const { characterId, tryCount } = await request.json(); + const { characterId, tryCount, triedCharacterIds } = await request.json(); + const normalizedTriedCharacterIds = Array.isArray(triedCharacterIds) + ? triedCharacterIds.filter((id): id is string => typeof id === 'string') + : []; if (!characterId) { return json({ error: 'Missing characterId' }, { status: 400 }); @@ -51,7 +54,8 @@ export async function POST({ request, locals }) { await db.insert(userCharacterHistory).values({ userId: locals.user.id, characterHistoryId: todayHistoryEntry.id, - tryCount: tryCount + tryCount: tryCount, + triedCharacterIds: normalizedTriedCharacterIds }); } } else { diff --git a/src/routes/(game)/profile/+page.server.ts b/src/routes/(game)/profile/+page.server.ts index bde74df..2c1de7c 100644 --- a/src/routes/(game)/profile/+page.server.ts +++ b/src/routes/(game)/profile/+page.server.ts @@ -3,7 +3,7 @@ import type { Actions, PageServerLoad } from './$types'; import { auth } from '$lib/server/auth'; import { db } from '$lib/server/db'; import { session, userCharacterHistory, characterHistory, character, friendship, user } from '$lib/server/db/schema'; -import { and, desc, eq, or, sql } from 'drizzle-orm'; +import { and, desc, eq, inArray, or, sql } from 'drizzle-orm'; import { APIError } from 'better-auth/api'; export const load: PageServerLoad = async (event) => { @@ -20,12 +20,13 @@ export const load: PageServerLoad = async (event) => { .where(eq(session.userId, event.locals.user.id)); // Fetch daily history for this user - const dailyHistory = await db + const dailyHistoryRaw = await db .select({ id: userCharacterHistory.id, characterId: characterHistory.characterId, date: characterHistory.date, tryCount: userCharacterHistory.tryCount, + triedCharacterIds: userCharacterHistory.triedCharacterIds, won: characterHistory.won, characterName: character.name, characterImage: character.pictureUrl @@ -36,6 +37,30 @@ export const load: PageServerLoad = async (event) => { .where(eq(userCharacterHistory.userId, event.locals.user.id)) .orderBy(desc(characterHistory.date)); + const uniqueTriedCharacterIds = Array.from(new Set( + dailyHistoryRaw.flatMap((entry) => entry.triedCharacterIds ?? []) + )); + + const triedCharacters = uniqueTriedCharacterIds.length > 0 + ? await db + .select({ + id: character.id, + name: character.name, + pictureUrl: character.pictureUrl + }) + .from(character) + .where(inArray(character.id, uniqueTriedCharacterIds)) + : []; + + const triedCharactersById = new Map(triedCharacters.map((entry) => [entry.id, entry])); + + const dailyHistory = dailyHistoryRaw.map((entry) => ({ + ...entry, + triedCharacters: (entry.triedCharacterIds ?? []) + .map((characterId) => triedCharactersById.get(characterId)) + .filter((triedEntry): triedEntry is (typeof triedCharacters)[number] => !!triedEntry) + })); + const incomingRequests = await db .select({ id: friendship.id, diff --git a/src/routes/(game)/profile/+page.svelte b/src/routes/(game)/profile/+page.svelte index f64e8ee..276366b 100644 --- a/src/routes/(game)/profile/+page.svelte +++ b/src/routes/(game)/profile/+page.svelte @@ -9,6 +9,21 @@ form?: { success?: boolean; message?: string } | null; } + interface DailyHistoryEntry { + id: string; + characterId: string | null; + date: number; + tryCount: number; + won: number; + characterName: string; + characterImage: string | null; + triedCharacters?: Array<{ + id: string; + name: string; + pictureUrl: string | null; + }>; + } + let { data, form }: Props = $props(); let isLoading = $state(false); @@ -20,7 +35,7 @@ let newPassword = $state(''); let confirmPassword = $state(''); let sessions = $derived(data.sessions || []); - let dailyHistory = $derived(data.dailyHistory || []); + let dailyHistory = $derived((data.dailyHistory || []) as DailyHistoryEntry[]); let friends = $derived(data.friends || []); let incomingRequests = $derived(data.incomingRequests || []); let outgoingRequests = $derived(data.outgoingRequests || []); @@ -455,6 +470,29 @@ day: 'numeric' })}

+
+

+ {$t.game.profile.triedCharactersTitle} +

+ {#if day.triedCharacters && day.triedCharacters.length > 0} +
+ {#each day.triedCharacters as triedCharacter (triedCharacter.id)} + + {#if triedCharacter.pictureUrl} + {triedCharacter.name} + {/if} + {triedCharacter.name} + + {/each} +
+ {:else} +

{$t.game.profile.noTriedCharacters}

+ {/if} +