- Added lib/dateUtils.ts for consistent timezone handling - Updated app/page.tsx and app/api/daily/route.ts to use Europe/Berlin timezone - Updated lib/gameState.ts to sync client-side daily check with server time - Exposed TZ env var to client in next.config.ts
82 lines
2.6 KiB
TypeScript
82 lines
2.6 KiB
TypeScript
import Game from '@/components/Game';
|
|
import { getTodayISOString } from '@/lib/dateUtils';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
import { PrismaClient } from '@prisma/client';
|
|
|
|
// PrismaClient is attached to the `global` object in development to prevent
|
|
// exhausting your database connection limit.
|
|
const globalForPrisma = global as unknown as { prisma: PrismaClient };
|
|
|
|
const prisma = globalForPrisma.prisma || new PrismaClient();
|
|
|
|
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma;
|
|
|
|
async function getDailyPuzzle() {
|
|
try {
|
|
const today = getTodayISOString();
|
|
console.log(`[getDailyPuzzle] Checking puzzle for date: ${today}`);
|
|
|
|
let dailyPuzzle = await prisma.dailyPuzzle.findUnique({
|
|
where: { date: today },
|
|
include: { song: true },
|
|
});
|
|
|
|
if (!dailyPuzzle) {
|
|
console.log('[getDailyPuzzle] No puzzle found, attempting to create...');
|
|
const songsCount = await prisma.song.count();
|
|
console.log(`[getDailyPuzzle] Found ${songsCount} songs in DB`);
|
|
|
|
if (songsCount > 0) {
|
|
const skip = Math.floor(Math.random() * songsCount);
|
|
const randomSong = await prisma.song.findFirst({ skip });
|
|
|
|
if (randomSong) {
|
|
try {
|
|
dailyPuzzle = await prisma.dailyPuzzle.create({
|
|
data: { date: today, songId: randomSong.id },
|
|
include: { song: true },
|
|
});
|
|
console.log(`[getDailyPuzzle] Created puzzle for song: ${randomSong.title}`);
|
|
} catch (createError) {
|
|
// Handle race condition: if another request created it in the meantime
|
|
console.log('[getDailyPuzzle] Creation failed, trying to fetch again (likely race condition)');
|
|
dailyPuzzle = await prisma.dailyPuzzle.findUnique({
|
|
where: { date: today },
|
|
include: { song: true },
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
console.log('[getDailyPuzzle] No songs available to create puzzle');
|
|
}
|
|
}
|
|
|
|
if (!dailyPuzzle) {
|
|
console.log('[getDailyPuzzle] Failed to get or create puzzle');
|
|
return null;
|
|
}
|
|
|
|
return {
|
|
id: dailyPuzzle.id,
|
|
audioUrl: `/uploads/${dailyPuzzle.song.filename}`,
|
|
songId: dailyPuzzle.songId,
|
|
title: dailyPuzzle.song.title,
|
|
artist: dailyPuzzle.song.artist,
|
|
coverImage: dailyPuzzle.song.coverImage ? `/uploads/covers/${dailyPuzzle.song.coverImage}` : null,
|
|
};
|
|
} catch (e) {
|
|
console.error('[getDailyPuzzle] Error:', e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export default async function Home() {
|
|
const dailyPuzzle = await getDailyPuzzle();
|
|
|
|
return (
|
|
<Game dailyPuzzle={dailyPuzzle} />
|
|
);
|
|
}
|