2025-08-15 15:02:11 -07:00
|
|
|
import { PrismaClient } from "@prisma/client";
|
|
|
|
import Logger from "../utils/logger";
|
|
|
|
|
2025-08-15 20:52:38 +00:00
|
|
|
const logger = new Logger();
|
|
|
|
|
2025-08-15 15:02:11 -07:00
|
|
|
class RecipeModel {
|
|
|
|
private prisma: PrismaClient;
|
|
|
|
|
2025-08-15 20:52:38 +00:00
|
|
|
constructor() {
|
|
|
|
this.prisma = new PrismaClient();
|
|
|
|
}
|
|
|
|
|
2025-08-15 15:02:11 -07:00
|
|
|
async getAllRecipes(): Promise<any[]> {
|
2025-08-15 20:52:38 +00:00
|
|
|
try {
|
|
|
|
return await this.prisma.recipes.findMany();
|
|
|
|
} catch (err) {
|
2025-08-15 15:02:11 -07:00
|
|
|
console.error("Error fetching all recipes:", err);
|
|
|
|
throw new Error(err instanceof Error ? err.message : "Unknown error");
|
2025-08-15 20:52:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-08-15 15:02:11 -07:00
|
|
|
async findById(id: number): Promise<any | null> {
|
2025-08-15 20:52:38 +00:00
|
|
|
try {
|
|
|
|
const recipe = await this.prisma.recipes.findUnique({
|
|
|
|
where: { id },
|
|
|
|
include: { recipeSteps: true, recipeIngredients: true },
|
|
|
|
});
|
|
|
|
if (!recipe) {
|
2025-08-15 15:02:11 -07:00
|
|
|
logger.warn(`Recipe with id ${id} cannot be found`);
|
2025-08-15 20:52:38 +00:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
const data = {
|
|
|
|
details: {
|
|
|
|
id: recipe.id,
|
|
|
|
name: recipe.name,
|
|
|
|
author: recipe.author,
|
|
|
|
cuisine: recipe.cuisine,
|
|
|
|
stars: recipe.stars,
|
|
|
|
prep_minutes: recipe.prep_minutes,
|
|
|
|
cook_minutes: recipe.cook_minutes,
|
|
|
|
},
|
|
|
|
ingredients: recipe.recipeIngredients.map((ing) => ing.raw),
|
2025-08-15 15:02:11 -07:00
|
|
|
steps: recipe.recipeSteps.map((step) => ({
|
2025-08-15 20:52:38 +00:00
|
|
|
step_number: step.step_number,
|
|
|
|
instruction: step.instruction,
|
|
|
|
})),
|
|
|
|
};
|
|
|
|
return data;
|
|
|
|
} catch (err) {
|
|
|
|
console.log("Error finding recipe:", err);
|
2025-08-15 15:02:11 -07:00
|
|
|
logger.error("Error finding recipe", {
|
|
|
|
message: err instanceof Error ? err.message : "Unknown error",
|
|
|
|
});
|
|
|
|
throw new Error(err instanceof Error ? err.message : "Unknown error");
|
2025-08-15 20:52:38 +00:00
|
|
|
}
|
|
|
|
}
|
2025-08-15 15:02:11 -07:00
|
|
|
|
|
|
|
async addRecipe(recipeData: {
|
|
|
|
name: string;
|
|
|
|
author: string;
|
|
|
|
cuisine: string;
|
|
|
|
stars: number;
|
|
|
|
ingredients: string[];
|
|
|
|
steps: { [key: string]: string };
|
|
|
|
prep_minutes: number;
|
|
|
|
cook_minutes: number;
|
|
|
|
}): Promise<any> {
|
2025-08-15 20:52:38 +00:00
|
|
|
const {
|
|
|
|
name,
|
|
|
|
author,
|
|
|
|
cuisine,
|
|
|
|
stars,
|
|
|
|
ingredients,
|
|
|
|
steps,
|
|
|
|
prep_minutes,
|
|
|
|
cook_minutes,
|
|
|
|
} = recipeData;
|
|
|
|
try {
|
|
|
|
const createdRecipe = await this.prisma.recipes.create({
|
|
|
|
data: {
|
|
|
|
name,
|
|
|
|
author,
|
|
|
|
cuisine,
|
|
|
|
prep_minutes,
|
|
|
|
cook_minutes,
|
|
|
|
stars,
|
|
|
|
recipeIngredients: {
|
|
|
|
create: ingredients.map((ing) => ({ raw: ing })),
|
|
|
|
},
|
|
|
|
recipeSteps: {
|
|
|
|
create: Object.keys(steps).map((stepNumber) => ({
|
|
|
|
step_number: parseInt(stepNumber),
|
|
|
|
instruction: steps[stepNumber],
|
|
|
|
})),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
|
2025-08-15 15:02:11 -07:00
|
|
|
logger.info("New recipe created", {
|
2025-08-15 20:52:38 +00:00
|
|
|
id: createdRecipe.id,
|
|
|
|
name: createdRecipe.name,
|
|
|
|
});
|
|
|
|
return createdRecipe;
|
2025-08-15 15:02:11 -07:00
|
|
|
} catch (err) {
|
|
|
|
console.log("Error creating recipe:", err);
|
|
|
|
logger.error("Error creating recipe", {
|
|
|
|
message: err instanceof Error ? err.message : "Unknown error",
|
|
|
|
});
|
2025-08-15 20:52:38 +00:00
|
|
|
throw new Error("Failed to add recipe");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-08-15 15:02:11 -07:00
|
|
|
async setStars(id: number, stars: number): Promise<{ message: string }> {
|
2025-08-15 20:52:38 +00:00
|
|
|
try {
|
|
|
|
await this.prisma.recipes.update({
|
|
|
|
where: { id },
|
|
|
|
data: { stars },
|
|
|
|
});
|
2025-08-15 15:02:11 -07:00
|
|
|
return { message: "Stars updated" };
|
2025-08-15 20:52:38 +00:00
|
|
|
} catch (err) {
|
|
|
|
console.error("Error updating stars:", err);
|
2025-08-15 15:02:11 -07:00
|
|
|
logger.error("Error setting stars", {
|
|
|
|
message: err instanceof Error ? err.message : "Unknown error",
|
|
|
|
});
|
|
|
|
throw new Error(err instanceof Error ? err.message : "Unknown error");
|
2025-08-15 20:52:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-08-15 15:02:11 -07:00
|
|
|
async deleteRecipe(id: number): Promise<{ message: string }> {
|
2025-08-15 20:52:38 +00:00
|
|
|
try {
|
|
|
|
await this.prisma.recipe_ingredients.deleteMany({
|
|
|
|
where: { recipe_id: id },
|
|
|
|
});
|
|
|
|
|
|
|
|
await this.prisma.recipe_steps.deleteMany({
|
|
|
|
where: { recipe_id: id },
|
|
|
|
});
|
|
|
|
const deletedRecipe = await this.prisma.recipes.delete({
|
|
|
|
where: { id },
|
|
|
|
});
|
2025-08-15 15:02:11 -07:00
|
|
|
logger.info("Recipe deleted", {
|
2025-08-15 20:52:38 +00:00
|
|
|
id: deletedRecipe.id,
|
|
|
|
name: deletedRecipe.name,
|
|
|
|
});
|
|
|
|
return { message: "Recipe deleted successfully" };
|
|
|
|
} catch (err) {
|
|
|
|
console.error("Error deleting recipe:", err);
|
2025-08-15 15:02:11 -07:00
|
|
|
logger.error("Error deleting recipe", {
|
|
|
|
message: err instanceof Error ? err.message : "Unknown error",
|
|
|
|
});
|
|
|
|
throw new Error(err instanceof Error ? err.message : "Unknown error");
|
2025-08-15 20:52:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-08-15 15:02:11 -07:00
|
|
|
|
|
|
|
export default RecipeModel;
|