diff --git a/backend/src/inventory/inventory.service.ts b/backend/src/inventory/inventory.service.ts index fe54f117..f490cbdd 100644 --- a/backend/src/inventory/inventory.service.ts +++ b/backend/src/inventory/inventory.service.ts @@ -94,6 +94,16 @@ export class InventoryService { where: { inventoryItemId: id, }, + select: { + id: true, + inventoryItemId: true, + amountUsed: true, + comment: true, + createdAt: true, + inventoryItem: { + select: { unit: true }, + }, + }, orderBy: { createdAt: 'desc', }, diff --git a/backend/src/recipes/recipes.controller.ts b/backend/src/recipes/recipes.controller.ts index 26498cb5..d97fe365 100644 --- a/backend/src/recipes/recipes.controller.ts +++ b/backend/src/recipes/recipes.controller.ts @@ -1,4 +1,4 @@ -import { Body, Controller, Get, Param, ParseIntPipe, Post, Patch } from '@nestjs/common'; +import { Body, Controller, Delete, Get, HttpCode, Param, ParseIntPipe, Post, Patch } from '@nestjs/common'; import { RecipesService } from './recipes.service'; import { CreateRecipeDto } from './dto/create-recipe.dto'; @@ -33,4 +33,10 @@ export class RecipesController { ) { return this.recipesService.update(id, createRecipeDto); } + + @Delete(':id') + @HttpCode(204) + async remove(@Param('id', ParseIntPipe) id: number) { + return this.recipesService.remove(id); + } } \ No newline at end of file diff --git a/backend/src/recipes/recipes.service.ts b/backend/src/recipes/recipes.service.ts index efe4d915..0b1848cd 100644 --- a/backend/src/recipes/recipes.service.ts +++ b/backend/src/recipes/recipes.service.ts @@ -345,6 +345,19 @@ export class RecipesService { return recipe; } + async remove(id: number) { + const existingRecipe = await this.prisma.recipe.findUnique({ + where: { id }, + }); + + if (!existingRecipe) { + throw new NotFoundException(`Recipe with id ${id} not found`); + } + + await this.prisma.recipeIngredient.deleteMany({ where: { recipeId: id } }); + await this.prisma.recipe.delete({ where: { id } }); + } + async create(createRecipeDto: CreateRecipeDto) { const recipe = await this.prisma.recipe.create({ data: { diff --git a/frontend/app/inventory/InventoryConsumptionHistory.tsx b/frontend/app/inventory/InventoryConsumptionHistory.tsx index 01d25786..4c3df17b 100644 --- a/frontend/app/inventory/InventoryConsumptionHistory.tsx +++ b/frontend/app/inventory/InventoryConsumptionHistory.tsx @@ -104,7 +104,7 @@ export default function InventoryConsumptionHistory({ id }: Props) { }} >
- Använt: {entry.amountUsed} + Använt: {entry.amountUsed}{entry.inventoryItem?.unit ? ` ${entry.inventoryItem.unit}` : ''}
Tid: {formatDateTime(entry.createdAt)} diff --git a/frontend/app/recipes/RecipePreview.tsx b/frontend/app/recipes/RecipePreview.tsx index 5ff61fb3..fa8a3849 100644 --- a/frontend/app/recipes/RecipePreview.tsx +++ b/frontend/app/recipes/RecipePreview.tsx @@ -58,6 +58,32 @@ export default function RecipePreview({ recipes }: Props) { const [error, setError] = useState(null); const [isPending, startTransition] = useTransition(); + const selectAndLoad = (id: string) => { + setSelectedRecipeId(id); + setError(null); + setPreview(null); + + startTransition(async () => { + try { + const res = await fetch(`/api/recipe-preview-proxy?id=${id}`, { + method: 'GET', + cache: 'no-store', + }); + + if (!res.ok) { + const errorMessage = await parseErrorResponse(res); + throw new Error(errorMessage); + } + + const data: RecipeInventoryPreview = await res.json(); + setPreview(data); + } catch (err) { + const message = err instanceof Error ? err.message : 'Ett okänt fel inträffade.'; + setError(message); + } + }); + }; + const loadPreview = () => { setError(null); setPreview(null); @@ -88,46 +114,49 @@ export default function RecipePreview({ recipes }: Props) { }); }; + const listedRecipes = recipes.slice(0, 10); + return (
-
-

Recept mot hemmavaror

+
+
+

Recept mot hemmavaror

- + -
- - {selectedRecipeId && ( +
+ + {selectedRecipeId && ( )} +
+ + {error ?

{error}

: null}
- {error ?

{error}

: null} + {/* Receptlista till höger */} +
+

Mina recept

+
    + {listedRecipes.map((recipe) => ( +
  • + +
  • + ))} +
+
{preview ? ( diff --git a/frontend/app/recipes/[id]/edit/page.tsx b/frontend/app/recipes/[id]/edit/page.tsx index d4f6c466..beb4e693 100644 --- a/frontend/app/recipes/[id]/edit/page.tsx +++ b/frontend/app/recipes/[id]/edit/page.tsx @@ -20,6 +20,7 @@ export default function EditRecipePage() { const [products, setProducts] = useState([]); const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); + const [isDeleting, setIsDeleting] = useState(false); const [error, setError] = useState(null); useEffect(() => { @@ -239,19 +240,45 @@ export default function EditRecipePage() {
)} -
- - +
+
+ + + +
diff --git a/frontend/features/inventory/types.ts b/frontend/features/inventory/types.ts index 8025bbb4..ccbe0e95 100644 --- a/frontend/features/inventory/types.ts +++ b/frontend/features/inventory/types.ts @@ -53,6 +53,7 @@ export type InventoryConsumption = { amountUsed: string; comment: string | null; createdAt: string; + inventoryItem?: { unit: string }; }; export type RecipeIngredient = { id: number;