feat: add tried characters tracking and display in daily game profile
Build Docker Image / build (push) Successful in 1m10s
Build Docker Image / build (push) Successful in 1m10s
This commit is contained in:
@@ -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)
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 @@
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.28em] text-amber-100 text-center">{$t.game.daily.friendsToday}</p>
|
||||
<div class="mt-4 space-y-2">
|
||||
{#each data.friendsTodayResults as friendResult (friendResult.userId)}
|
||||
<div class="flex items-center justify-between rounded-lg border border-white/10 bg-slate-950/50 px-4 py-2">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="rounded-lg border border-white/10 bg-slate-950/50 px-4 py-3">
|
||||
<div class="flex items-center justify-between gap-4">
|
||||
<div class="flex items-center gap-3">
|
||||
{#if friendResult.image}
|
||||
<img
|
||||
src={friendResult.image}
|
||||
@@ -331,10 +335,34 @@
|
||||
</div>
|
||||
{/if}
|
||||
<p class="text-sm font-semibold text-slate-100">{friendResult.name}</p>
|
||||
</div>
|
||||
<p class="text-sm text-amber-300">
|
||||
{friendResult.tryCount} {friendResult.tryCount > 1 ? $t.game.daily.friendTryPlural : $t.game.daily.friendTrySingular}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-3 border-t border-white/10 pt-2">
|
||||
<p class="text-[11px] font-semibold uppercase tracking-[0.2em] text-amber-100">
|
||||
{$t.game.daily.friendsTriedCharacters}
|
||||
</p>
|
||||
{#if friendResult.triedCharacters && friendResult.triedCharacters.length > 0}
|
||||
<div class="mt-2 flex flex-wrap gap-2">
|
||||
{#each friendResult.triedCharacters as triedCharacter (triedCharacter.id)}
|
||||
<span class="inline-flex items-center gap-2 rounded-full border border-white/15 bg-white/5 px-2.5 py-1 text-xs text-slate-200">
|
||||
{#if triedCharacter.pictureUrl}
|
||||
<img
|
||||
src={triedCharacter.pictureUrl}
|
||||
alt={triedCharacter.name}
|
||||
class="h-4 w-4 rounded-full object-cover"
|
||||
/>
|
||||
{/if}
|
||||
{triedCharacter.name}
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
{:else}
|
||||
<p class="mt-1 text-xs text-slate-500">{$t.game.daily.friendsNoTriedCharacters}</p>
|
||||
{/if}
|
||||
</div>
|
||||
<p class="text-sm text-amber-300">
|
||||
{friendResult.tryCount} {friendResult.tryCount > 1 ? $t.game.daily.friendTryPlural : $t.game.daily.friendTrySingular}
|
||||
</p>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user