107 lines
2.5 KiB
TypeScript
107 lines
2.5 KiB
TypeScript
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<number> {
|
|
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<DailyVisitResponse> => {
|
|
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,
|
|
};
|
|
});
|