- Add UserFavorites MongoDB model with ObjectId references - Create authenticated API endpoints for favorites management - Add Heart icon and FavoriteButton components with toggle functionality - Display favorite button below recipe tags for logged-in users - Add Favoriten navigation link (visible only when authenticated) - Create favorites page with grid layout and search functionality - Store favorites by MongoDB ObjectId for data integrity 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
112 lines
2.7 KiB
TypeScript
112 lines
2.7 KiB
TypeScript
import { json, type RequestHandler } from '@sveltejs/kit';
|
|
import { UserFavorites } from '../../../../models/UserFavorites';
|
|
import { Recipe } from '../../../../models/Recipe';
|
|
import { dbConnect, dbDisconnect } from '../../../../utils/db';
|
|
import { error } from '@sveltejs/kit';
|
|
import mongoose from 'mongoose';
|
|
|
|
export const GET: RequestHandler = async ({ locals }) => {
|
|
const session = await locals.auth();
|
|
|
|
if (!session?.user?.nickname) {
|
|
throw error(401, 'Authentication required');
|
|
}
|
|
|
|
await dbConnect();
|
|
|
|
try {
|
|
const userFavorites = await UserFavorites.findOne({
|
|
username: session.user.nickname
|
|
}).lean();
|
|
|
|
await dbDisconnect();
|
|
|
|
return json({
|
|
favorites: userFavorites?.favorites || []
|
|
});
|
|
} catch (e) {
|
|
await dbDisconnect();
|
|
throw error(500, 'Failed to fetch favorites');
|
|
}
|
|
};
|
|
|
|
export const POST: RequestHandler = async ({ request, locals }) => {
|
|
const session = await locals.auth();
|
|
|
|
if (!session?.user?.nickname) {
|
|
throw error(401, 'Authentication required');
|
|
}
|
|
|
|
const { recipeId } = await request.json();
|
|
|
|
if (!recipeId) {
|
|
throw error(400, 'Recipe ID required');
|
|
}
|
|
|
|
await dbConnect();
|
|
|
|
try {
|
|
// Validate that the recipe exists and get its ObjectId
|
|
const recipe = await Recipe.findOne({ short_name: recipeId });
|
|
if (!recipe) {
|
|
await dbDisconnect();
|
|
throw error(404, 'Recipe not found');
|
|
}
|
|
|
|
await UserFavorites.findOneAndUpdate(
|
|
{ username: session.user.nickname },
|
|
{ $addToSet: { favorites: recipe._id } },
|
|
{ upsert: true, new: true }
|
|
);
|
|
|
|
await dbDisconnect();
|
|
|
|
return json({ success: true });
|
|
} catch (e) {
|
|
await dbDisconnect();
|
|
if (e instanceof Error && e.message.includes('404')) {
|
|
throw e;
|
|
}
|
|
throw error(500, 'Failed to add favorite');
|
|
}
|
|
};
|
|
|
|
export const DELETE: RequestHandler = async ({ request, locals }) => {
|
|
const session = await locals.auth();
|
|
|
|
if (!session?.user?.nickname) {
|
|
throw error(401, 'Authentication required');
|
|
}
|
|
|
|
const { recipeId } = await request.json();
|
|
|
|
if (!recipeId) {
|
|
throw error(400, 'Recipe ID required');
|
|
}
|
|
|
|
await dbConnect();
|
|
|
|
try {
|
|
// Find the recipe's ObjectId
|
|
const recipe = await Recipe.findOne({ short_name: recipeId });
|
|
if (!recipe) {
|
|
await dbDisconnect();
|
|
throw error(404, 'Recipe not found');
|
|
}
|
|
|
|
await UserFavorites.findOneAndUpdate(
|
|
{ username: session.user.nickname },
|
|
{ $pull: { favorites: recipe._id } }
|
|
);
|
|
|
|
await dbDisconnect();
|
|
|
|
return json({ success: true });
|
|
} catch (e) {
|
|
await dbDisconnect();
|
|
if (e instanceof Error && e.message.includes('404')) {
|
|
throw e;
|
|
}
|
|
throw error(500, 'Failed to remove favorite');
|
|
}
|
|
}; |