import { useSession } from 'h3'; interface DailyVisitResponse { message: string; reward: { coins: number; streakBonus: boolean; }; updatedCoins: number; } /** * A helper function to safely get the authenticated user's ID from the session. */ async function getUserIdFromSession(event: any): Promise { const session = await useSession(event, { password: process.env.SESSION_PASSWORD, }); const userId = session.data?.user?.id; if (!userId) { throw createError({ statusCode: 401, statusMessage: 'Unauthorized' }); } return userId; } /** * Creates a Date object for the start of a given day in UTC. */ function getStartOfDay(date: Date): Date { const startOfDay = new Date(date); startOfDay.setUTCHours(0, 0, 0, 0); return startOfDay; } export default defineEventHandler(async (event): Promise => { const userId = await getUserIdFromSession(event); const today = getStartOfDay(new Date()); // 1. Check if the user has already claimed the reward today const existingVisit = await prisma.dailyVisit.findUnique({ where: { userId_date: { userId, date: today, }, }, }); if (existingVisit) { throw createError({ statusCode: 409, statusMessage: 'Daily visit reward has already been claimed today.', }); } // 2. Check for a 5-day consecutive streak (i.e., visits on the 4 previous days) const previousDates = Array.from({ length: 4 }, (_, i) => { const d = new Date(today); d.setUTCDate(d.getUTCDate() - (i + 1)); return d; }); const priorVisitsCount = await prisma.dailyVisit.count({ where: { userId, date: { in: previousDates, }, }, }); const hasStreak = priorVisitsCount === 4; // 3. Calculate rewards and update the database in a transaction let totalReward = 1; // Base reward if (hasStreak) { totalReward += 10; // Streak bonus } const [, updatedUser] = await prisma.$transaction([ prisma.dailyVisit.create({ data: { userId, date: today, }, }), prisma.user.update({ where: { id: userId }, data: { coins: { increment: totalReward, }, }, }), ]); // 4. Return the response return { message: hasStreak ? 'Daily visit and streak bonus claimed!' : 'Daily visit claimed!', reward: { coins: totalReward, streakBonus: hasStreak, }, updatedCoins: updatedUser.coins, }; });