Files
homepage/src/routes/[recipeLang]/[name]/+page.server.ts
Alexander Bocken 6de3d76504 refactor: unify recipe routes into [recipeLang] slug with full bilingual support
Consolidate /rezepte and /recipes routes into single [recipeLang] structure to eliminate code duplication. All pages now use conditional API routing and reactive labels based on language parameter.

- Merge duplicate route structures into /[recipeLang] with 404 for invalid slugs
- Add English API endpoints for search, favorites, tags, and categories
- Implement language dropdown in header with localStorage persistence
- Convert all pages to use Svelte 5 runes (, , )
- Add German-only redirects (301) for add/edit pages
- Make all view pages (list, detail, filters, search, favorites) fully bilingual
- Remove floating language switcher in favor of header dropdown
2025-12-26 21:19:27 +01:00

73 lines
2.6 KiB
TypeScript

import { redirect, error } from '@sveltejs/kit';
export const actions = {
toggleFavorite: async ({ request, locals, url, fetch }) => {
const session = await locals.auth();
if (!session?.user?.nickname) {
throw error(401, 'Authentication required');
}
const formData = await request.formData();
const recipeId = formData.get('recipeId') as string;
const isFavorite = formData.get('isFavorite') === 'true';
if (!recipeId) {
throw error(400, 'Recipe ID required');
}
try {
// Use the existing API endpoint
const method = isFavorite ? 'DELETE' : 'POST';
const response = await fetch('/api/rezepte/favorites', {
method,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ recipeId }),
});
if (!response.ok) {
const errorData = await response.text();
console.error('API error:', response.status, errorData);
throw error(response.status, `Failed to toggle favorite: ${errorData}`);
}
// Redirect back to the same page to refresh the state
throw redirect(303, url.pathname);
} catch (e) {
// If it's a redirect, let it through
if (e && typeof e === 'object' && 'status' in e && e.status === 303) {
throw e;
}
console.error('Favorite toggle error:', e);
throw error(500, 'Failed to toggle favorite');
}
},
swapYeast: async ({ request, url }) => {
const formData = await request.formData();
const yeastId = parseInt(formData.get('yeastId') as string);
// Build new URL
const newUrl = new URL(url.pathname, url.origin);
// Restore all parameters from the form data (they were submitted as currentParam_*)
for (const [key, value] of formData.entries()) {
if (key.startsWith('currentParam_')) {
const paramName = key.substring('currentParam_'.length);
newUrl.searchParams.set(paramName, value as string);
}
}
// Toggle the yeast flag - if it exists, remove it; if not, add it
const yeastParam = `y${yeastId}`;
if (newUrl.searchParams.has(yeastParam)) {
newUrl.searchParams.delete(yeastParam);
} else {
newUrl.searchParams.set(yeastParam, '1');
}
throw redirect(303, newUrl.toString());
}
};