habits.andr33v.ru/server/api/onboarding/complete-habit.post.ts

86 lines
2.4 KiB
TypeScript

import { getAuthenticatedUserId } from '~/server/utils/auth';
import prisma from '~/server/utils/prisma'; // Ensure prisma is imported
const ONBOARDING_REWARD_COINS = 75;
interface OnboardingCompletionResponse {
message: string;
updatedCoins: number;
}
// Helper to get the start of the day in UTC
function getStartOfDay(date: Date): Date {
const d = new Date(date);
d.setUTCHours(0, 0, 0, 0);
return d;
}
/**
* A special endpoint for the onboarding funnel to complete a habit.
* This provides a fixed reward and has simpler logic than the main completion endpoint.
* ONLY callable by anonymous users.
*/
export default defineEventHandler(async (event): Promise<OnboardingCompletionResponse> => {
const userId = getAuthenticatedUserId(event);
const { habitId } = await readBody(event);
// Fetch the full user to check their anonymous status
const user = await prisma.user.findUnique({
where: { id: userId },
select: { id: true, isAnonymous: true }
});
// Ensure only anonymous users can use this endpoint
if (!user || !user.isAnonymous) {
throw createError({ statusCode: 403, statusMessage: 'Forbidden: This endpoint is for anonymous onboarding users only.' });
}
if (!habitId || typeof habitId !== 'number') {
throw createError({ statusCode: 400, statusMessage: 'Invalid habit ID.' });
}
const habit = await prisma.habit.findFirst({
where: { id: habitId, userId: userId }
});
if (!habit) {
throw createError({ statusCode: 404, statusMessage: 'Habit not found for this user.' });
}
const startOfToday = getStartOfDay(new Date());
const existingCompletion = await prisma.habitCompletion.findFirst({
where: {
habitId: habitId,
date: startOfToday,
},
});
if (existingCompletion) {
throw createError({ statusCode: 409, statusMessage: 'Habit already completed today.' });
}
// Use a transaction to ensure both operations succeed or fail together
const [, updatedUser] = await prisma.$transaction([
prisma.habitCompletion.create({
data: {
habitId: habitId,
date: startOfToday,
},
}),
prisma.user.update({
where: { id: userId },
data: {
coins: {
increment: ONBOARDING_REWARD_COINS,
},
},
}),
]);
return {
message: 'Onboarding habit completed successfully!',
updatedCoins: updatedUser.coins,
};
});