From 84d6cfeb07095c39fd5ad498aa0976fb144b1e61 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Wed, 1 Jul 2026 08:10:11 +0200 Subject: [PATCH] feat(recipes): full recipe CRUD with photos, print, version history List, detail, new, edit pages. Server-side pagination, dietary tags, difficulty. Photo upload to S3-compatible storage. Version history. Multi-select grid with bulk delete/visibility. Print view. Delete confirmation dialog. --- apps/web/app/(app)/layout.tsx | 10 + apps/web/app/(app)/recipes/[id]/cook/page.tsx | 46 +++ apps/web/app/(app)/recipes/[id]/edit/page.tsx | 67 +++ apps/web/app/(app)/recipes/[id]/page.tsx | 290 +++++++++++++ .../web/app/(app)/recipes/[id]/print/page.tsx | 142 +++++++ apps/web/app/(app)/recipes/can-cook/page.tsx | 58 +++ apps/web/app/(app)/recipes/new/page.tsx | 18 + apps/web/app/(app)/recipes/page.tsx | 48 +++ .../comments/[commentId]/reactions/route.ts | 102 +++++ .../app/api/v1/recipes/[id]/comments/route.ts | 82 ++++ .../app/api/v1/recipes/[id]/cooked/route.ts | 74 ++++ .../app/api/v1/recipes/[id]/favorite/route.ts | 28 ++ .../api/v1/recipes/[id]/nutrition/route.ts | 62 +++ .../web/app/api/v1/recipes/[id]/rate/route.ts | 49 +++ apps/web/app/api/v1/recipes/[id]/route.ts | 177 ++++++++ .../[id]/versions/[versionId]/route.ts | 148 +++++++ .../app/api/v1/recipes/[id]/versions/route.ts | 32 ++ apps/web/app/api/v1/recipes/bulk/route.ts | 45 ++ apps/web/app/api/v1/recipes/route.ts | 167 ++++++++ .../components/recipe/adapt-recipe-button.tsx | 187 +++++++++ .../recipe/add-to-shopping-list-button.tsx | 220 ++++++++++ .../components/recipe/ai-generate-dialog.tsx | 287 +++++++++++++ .../components/recipe/can-cook-content.tsx | 138 +++++++ .../recipe/delete-recipe-button.tsx | 67 +++ .../components/recipe/dietary-tag-picker.tsx | 51 +++ .../recipe/drink-pairing-button.tsx | 155 +++++++ .../components/recipe/meal-pairing-button.tsx | 249 +++++++++++ .../components/recipe/new-recipe-header.tsx | 11 + .../web/components/recipe/nutrition-panel.tsx | 145 +++++++ .../components/recipe/photo-import-button.tsx | 83 ++++ apps/web/components/recipe/photo-uploader.tsx | 117 ++++++ apps/web/components/recipe/print-button.tsx | 18 + apps/web/components/recipe/print-trigger.tsx | 12 + apps/web/components/recipe/recipe-card.tsx | 85 ++++ apps/web/components/recipe/recipe-form.tsx | 388 ++++++++++++++++++ .../components/recipe/recipes-empty-state.tsx | 37 ++ apps/web/components/recipe/recipes-grid.tsx | 321 +++++++++++++++ apps/web/components/recipe/recipes-header.tsx | 84 ++++ apps/web/components/recipe/serving-scaler.tsx | 156 +++++++ .../recipe/substitute-ingredient-popover.tsx | 100 +++++ .../components/recipe/translate-button.tsx | 124 ++++++ .../components/recipe/url-import-dialog.tsx | 124 ++++++ .../components/recipe/variations-button.tsx | 46 +++ .../components/recipe/variations-dialog.tsx | 273 ++++++++++++ .../recipe/version-history-button.tsx | 177 ++++++++ 45 files changed, 5300 insertions(+) create mode 100644 apps/web/app/(app)/layout.tsx create mode 100644 apps/web/app/(app)/recipes/[id]/cook/page.tsx create mode 100644 apps/web/app/(app)/recipes/[id]/edit/page.tsx create mode 100644 apps/web/app/(app)/recipes/[id]/page.tsx create mode 100644 apps/web/app/(app)/recipes/[id]/print/page.tsx create mode 100644 apps/web/app/(app)/recipes/can-cook/page.tsx create mode 100644 apps/web/app/(app)/recipes/new/page.tsx create mode 100644 apps/web/app/(app)/recipes/page.tsx create mode 100644 apps/web/app/api/v1/recipes/[id]/comments/[commentId]/reactions/route.ts create mode 100644 apps/web/app/api/v1/recipes/[id]/comments/route.ts create mode 100644 apps/web/app/api/v1/recipes/[id]/cooked/route.ts create mode 100644 apps/web/app/api/v1/recipes/[id]/favorite/route.ts create mode 100644 apps/web/app/api/v1/recipes/[id]/nutrition/route.ts create mode 100644 apps/web/app/api/v1/recipes/[id]/rate/route.ts create mode 100644 apps/web/app/api/v1/recipes/[id]/route.ts create mode 100644 apps/web/app/api/v1/recipes/[id]/versions/[versionId]/route.ts create mode 100644 apps/web/app/api/v1/recipes/[id]/versions/route.ts create mode 100644 apps/web/app/api/v1/recipes/bulk/route.ts create mode 100644 apps/web/app/api/v1/recipes/route.ts create mode 100644 apps/web/components/recipe/adapt-recipe-button.tsx create mode 100644 apps/web/components/recipe/add-to-shopping-list-button.tsx create mode 100644 apps/web/components/recipe/ai-generate-dialog.tsx create mode 100644 apps/web/components/recipe/can-cook-content.tsx create mode 100644 apps/web/components/recipe/delete-recipe-button.tsx create mode 100644 apps/web/components/recipe/dietary-tag-picker.tsx create mode 100644 apps/web/components/recipe/drink-pairing-button.tsx create mode 100644 apps/web/components/recipe/meal-pairing-button.tsx create mode 100644 apps/web/components/recipe/new-recipe-header.tsx create mode 100644 apps/web/components/recipe/nutrition-panel.tsx create mode 100644 apps/web/components/recipe/photo-import-button.tsx create mode 100644 apps/web/components/recipe/photo-uploader.tsx create mode 100644 apps/web/components/recipe/print-button.tsx create mode 100644 apps/web/components/recipe/print-trigger.tsx create mode 100644 apps/web/components/recipe/recipe-card.tsx create mode 100644 apps/web/components/recipe/recipe-form.tsx create mode 100644 apps/web/components/recipe/recipes-empty-state.tsx create mode 100644 apps/web/components/recipe/recipes-grid.tsx create mode 100644 apps/web/components/recipe/recipes-header.tsx create mode 100644 apps/web/components/recipe/serving-scaler.tsx create mode 100644 apps/web/components/recipe/substitute-ingredient-popover.tsx create mode 100644 apps/web/components/recipe/translate-button.tsx create mode 100644 apps/web/components/recipe/url-import-dialog.tsx create mode 100644 apps/web/components/recipe/variations-button.tsx create mode 100644 apps/web/components/recipe/variations-dialog.tsx create mode 100644 apps/web/components/recipe/version-history-button.tsx diff --git a/apps/web/app/(app)/layout.tsx b/apps/web/app/(app)/layout.tsx new file mode 100644 index 0000000..4439a4f --- /dev/null +++ b/apps/web/app/(app)/layout.tsx @@ -0,0 +1,10 @@ +import { Nav } from "@/components/layout/nav"; + +export default function AppLayout({ children }: { children: React.ReactNode }) { + return ( + <> +