habits.andr33v.ru/server/api/village/harvest.post.ts

73 lines
2.3 KiB
TypeScript

import { getUserIdFromSession } from '../../utils/auth';
import { CROP_HARVEST_REWARD, isCropGrown } from '../../utils/village';
import { CropType } from '@prisma/client';
// --- Handler ---
export default defineEventHandler(async (event) => {
const userId = await getUserIdFromSession(event);
const { fieldId } = await readBody(event);
// 1. --- Validation ---
if (typeof fieldId !== 'number') {
throw createError({ statusCode: 400, statusMessage: 'Invalid request body. "fieldId" is required.' });
}
// 2. --- Find the target field and validate its state ---
const field = await prisma.villageObject.findFirst({
where: {
id: fieldId,
type: 'FIELD',
village: { userId: userId }, // Ensures ownership
},
});
if (!field) {
throw createError({ statusCode: 404, statusMessage: 'Field not found or you do not own it.' });
}
if (!field.cropType || !field.plantedAt) {
throw createError({ statusCode: 400, statusMessage: 'Nothing is planted in this field.' });
}
if (!isCropGrown(field.plantedAt, field.cropType)) {
throw createError({ statusCode: 400, statusMessage: 'Crop is not yet fully grown.' });
}
// 3. --- Grant rewards and clear field in a transaction ---
const reward = CROP_HARVEST_REWARD[field.cropType];
const [, , updatedField] = await prisma.$transaction([
// Grant EXP and Coins
prisma.user.update({
where: { id: userId },
data: {
exp: { increment: reward.exp },
coins: { increment: reward.coins },
},
}),
// Clear the crop from the field
prisma.villageObject.update({
where: { id: fieldId },
data: {
cropType: null,
plantedAt: null,
},
}),
// Re-fetch the field to return its cleared state
prisma.villageObject.findUniqueOrThrow({ where: { id: fieldId } }),
]);
return {
message: `${field.cropType} harvested successfully!`,
reward: reward,
updatedField: {
id: updatedField.id,
type: updatedField.type,
x: updatedField.x,
y: updatedField.y,
cropType: updatedField.cropType,
isGrown: false,
}
};
});