From aa4832e33f2300a5c1605f2906b93fc810709203 Mon Sep 17 00:00:00 2001 From: Daniel Kjellid Date: Tue, 18 Jun 2024 14:11:15 +0200 Subject: [PATCH 1/2] Optional ingredients --- .../components/IngredientAddDrawer.tsx | 2 +- .../components/IngredientsOverviewTable.tsx | 10 ++++++---- .../RecipeForm/IngredientGroupInput.tsx | 6 +++--- .../components/RecipeForm/RecipeForm.tsx | 20 ++++++++++++++----- .../components/RecipeForm/StepInput.tsx | 2 +- .../generated/models/IngredientCreateForm.ts | 2 +- .../models/RecipeIngredientRecord.ts | 2 +- nest/recipes/ingredients/forms.py | 4 ++-- .../0002_alter_recipeingredient_product.py | 20 +++++++++++++++++++ nest/recipes/ingredients/models.py | 2 ++ nest/recipes/ingredients/records.py | 6 ++++-- schema.json | 6 ++---- 12 files changed, 58 insertions(+), 24 deletions(-) create mode 100644 nest/recipes/ingredients/migrations/0002_alter_recipeingredient_product.py diff --git a/frontend/apps/ingredients/components/IngredientAddDrawer.tsx b/frontend/apps/ingredients/components/IngredientAddDrawer.tsx index bcc75b0d..1edb3513 100644 --- a/frontend/apps/ingredients/components/IngredientAddDrawer.tsx +++ b/frontend/apps/ingredients/components/IngredientAddDrawer.tsx @@ -58,7 +58,7 @@ function IngredientAddDrawer({ // Filter out products already assigned other ingredients. .filter( (product) => - !ingredients.flatMap((ingredient) => ingredient.product.id).includes(product.id) + !ingredients.flatMap((ingredient) => ingredient.product?.id).includes(product.id) ) .map((product) => ({ image: product.thumbnailUrl, diff --git a/frontend/apps/ingredients/components/IngredientsOverviewTable.tsx b/frontend/apps/ingredients/components/IngredientsOverviewTable.tsx index 20be4d04..98f64df0 100644 --- a/frontend/apps/ingredients/components/IngredientsOverviewTable.tsx +++ b/frontend/apps/ingredients/components/IngredientsOverviewTable.tsx @@ -21,10 +21,12 @@ function IngredientsOverviewTable({ data, onDeleteIngredient }: IngredientsOverv accessorKey: 'product.fullName', Cell: ({ row, renderedCellValue }) => (
- - - {renderedCellValue} - + + {row.original.product?.id && ( + + {renderedCellValue} + + )}
), }, diff --git a/frontend/apps/recipes/components/RecipeForm/IngredientGroupInput.tsx b/frontend/apps/recipes/components/RecipeForm/IngredientGroupInput.tsx index 19d78f23..04c96867 100644 --- a/frontend/apps/recipes/components/RecipeForm/IngredientGroupInput.tsx +++ b/frontend/apps/recipes/components/RecipeForm/IngredientGroupInput.tsx @@ -78,7 +78,7 @@ function IngredientInput({ data = { ...data, ingredient: ingredient || ({} as RecipeIngredientRecord), - portionQuantityUnit: ingredient?.product.unit || ({} as UnitRecord), + portionQuantityUnit: ingredient?.product?.unit || ({} as UnitRecord), } } else if (key === 'portionQuantityUnit') { const unit = units?.find((unit) => unit.id.toString() === event) @@ -115,8 +115,8 @@ function IngredientInput({ ) .map((ingredient) => ({ label: ingredient.title, - image: ingredient.product.thumbnailUrl, - description: ingredient.product.fullName, + image: ingredient.product?.thumbnailUrl, + description: ingredient.product?.fullName, value: ingredient.id.toString(), })), [ingredients, ingredientItemGroup, ingredientItem] diff --git a/frontend/apps/recipes/components/RecipeForm/RecipeForm.tsx b/frontend/apps/recipes/components/RecipeForm/RecipeForm.tsx index 1f70b5a7..680746f3 100644 --- a/frontend/apps/recipes/components/RecipeForm/RecipeForm.tsx +++ b/frontend/apps/recipes/components/RecipeForm/RecipeForm.tsx @@ -340,11 +340,21 @@ function RecipeForm({ recipe, ingredients, onSubmit }: RecipeFormProps) { /> } /> -
- - +
+
+ + +
+
+ + +
diff --git a/frontend/apps/recipes/components/RecipeForm/StepInput.tsx b/frontend/apps/recipes/components/RecipeForm/StepInput.tsx index f339710f..915d08e2 100644 --- a/frontend/apps/recipes/components/RecipeForm/StepInput.tsx +++ b/frontend/apps/recipes/components/RecipeForm/StepInput.tsx @@ -195,7 +195,7 @@ function StepInput({ variant="light" className="mt-5" disabled={!canBeDeleted} - onClick={() => onAction('inputDelete', stepNumber)} + onClick={() => onAction('inputDelete', stepNumber - 1)} > diff --git a/frontend/types/generated/models/IngredientCreateForm.ts b/frontend/types/generated/models/IngredientCreateForm.ts index 8a9e5a19..0771dd86 100644 --- a/frontend/types/generated/models/IngredientCreateForm.ts +++ b/frontend/types/generated/models/IngredientCreateForm.ts @@ -5,6 +5,6 @@ export type IngredientCreateForm = { title: string; - product: string; + product?: string; }; diff --git a/frontend/types/generated/models/RecipeIngredientRecord.ts b/frontend/types/generated/models/RecipeIngredientRecord.ts index af9f96d7..a79d95dd 100644 --- a/frontend/types/generated/models/RecipeIngredientRecord.ts +++ b/frontend/types/generated/models/RecipeIngredientRecord.ts @@ -8,6 +8,6 @@ import type { ProductRecord } from './ProductRecord'; export type RecipeIngredientRecord = { id: number; title: string; - product: ProductRecord; + product?: ProductRecord; }; diff --git a/nest/recipes/ingredients/forms.py b/nest/recipes/ingredients/forms.py index 6efc90d4..9a91bae9 100644 --- a/nest/recipes/ingredients/forms.py +++ b/nest/recipes/ingredients/forms.py @@ -14,8 +14,8 @@ class IngredientCreateForm(BaseModel): title: str = FormField( ..., order=1, help_text="User friendly title. E.g. Red tomatoes." ) - product_id: str = FormField( - ..., + product_id: str | None = FormField( + None, alias="product", order=2, component=FrontendComponents.SELECT.value, diff --git a/nest/recipes/ingredients/migrations/0002_alter_recipeingredient_product.py b/nest/recipes/ingredients/migrations/0002_alter_recipeingredient_product.py new file mode 100644 index 00000000..a46891e5 --- /dev/null +++ b/nest/recipes/ingredients/migrations/0002_alter_recipeingredient_product.py @@ -0,0 +1,20 @@ +# Generated by Django 4.2.7 on 2024-06-18 12:03 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('products', '0003_product_allergens_product_carbohydrates_and_more'), + ('recipes_ingredients', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='recipeingredient', + name='product', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='ingredient', to='products.product'), + ), + ] diff --git a/nest/recipes/ingredients/models.py b/nest/recipes/ingredients/models.py index fb8fcf05..7da4eee2 100644 --- a/nest/recipes/ingredients/models.py +++ b/nest/recipes/ingredients/models.py @@ -17,6 +17,8 @@ class RecipeIngredient(BaseModel): "products.Product", related_name="ingredient", on_delete=models.CASCADE, + blank=True, + null=True, ) objects = _RecipeIngredientManager() diff --git a/nest/recipes/ingredients/records.py b/nest/recipes/ingredients/records.py index a86b353a..b15f89ba 100644 --- a/nest/recipes/ingredients/records.py +++ b/nest/recipes/ingredients/records.py @@ -13,14 +13,16 @@ class RecipeIngredientRecord(BaseModel): id: int title: str - product: ProductRecord + product: ProductRecord | None @classmethod def from_db_model(cls, model: RecipeIngredient) -> RecipeIngredientRecord: return cls( id=model.id, title=model.title, - product=ProductRecord.from_product(model.product), + product=ProductRecord.from_product(model.product) + if model.product + else None, ) diff --git a/schema.json b/schema.json index 093a6ed0..41136650 100644 --- a/schema.json +++ b/schema.json @@ -2609,8 +2609,7 @@ "type": "object", "required": [ "id", - "title", - "product" + "title" ], "properties": { "id": { @@ -2968,8 +2967,7 @@ "x-form": true, "x-columns": 1, "required": [ - "title", - "product" + "title" ], "properties": { "title": { From e8257ad4938bec1201a02b63067556dc8a19ab27 Mon Sep 17 00:00:00 2001 From: Daniel Kjellid Date: Tue, 18 Jun 2024 14:14:07 +0200 Subject: [PATCH 2/2] Lint --- nest/recipes/plans/algorithm.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nest/recipes/plans/algorithm.py b/nest/recipes/plans/algorithm.py index 8012aa91..79675365 100644 --- a/nest/recipes/plans/algorithm.py +++ b/nest/recipes/plans/algorithm.py @@ -53,6 +53,9 @@ def _get_products_dataframe(self) -> pl.DataFrame: for item in group.ingredient_items: product = item.ingredient.product + if product is None: + continue + portion_quantity = item.portion_quantity * recipe_portion_factor converted_quantity = convert_unit_quantity(