63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
import { useSession } from 'h3';
|
|
|
|
interface HabitDto {
|
|
id: number;
|
|
name: string;
|
|
daysOfWeek: 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;
|
|
}
|
|
|
|
export default defineEventHandler(async (event): Promise<HabitDto> => {
|
|
const userId = await getUserIdFromSession(event);
|
|
const { name, daysOfWeek } = await readBody(event);
|
|
|
|
// --- Validation ---
|
|
if (!name || !Array.isArray(daysOfWeek)) {
|
|
throw createError({ statusCode: 400, statusMessage: 'Invalid input: name and daysOfWeek are required.' });
|
|
}
|
|
|
|
// Sanitize daysOfWeek to ensure it's a unique set of valid numbers
|
|
const validDays = daysOfWeek.filter(day => typeof day === 'number' && day >= 0 && day <= 6);
|
|
const sanitizedDays = [...new Set(validDays)].sort();
|
|
|
|
|
|
// --- Business Rule: Max 3 Habits ---
|
|
const habitCount = await prisma.habit.count({ where: { userId } });
|
|
if (habitCount >= 3) {
|
|
throw createError({ statusCode: 400, statusMessage: 'Maximum number of 3 habits reached.' });
|
|
}
|
|
|
|
// --- Create Habit ---
|
|
const newHabit = await prisma.habit.create({
|
|
data: {
|
|
userId,
|
|
name,
|
|
daysOfWeek: sanitizedDays,
|
|
},
|
|
});
|
|
|
|
// Set 201 Created status
|
|
setResponseStatus(event, 201);
|
|
|
|
// Return DTO
|
|
return {
|
|
id: newHabit.id,
|
|
name: newHabit.name,
|
|
daysOfWeek: newHabit.daysOfWeek as number[],
|
|
};
|
|
});
|