diff options
Diffstat (limited to 'kitchen/views_htmx.py')
| -rw-r--r-- | kitchen/views_htmx.py | 75 |
1 files changed, 28 insertions, 47 deletions
diff --git a/kitchen/views_htmx.py b/kitchen/views_htmx.py index a1e13f3..e9e8569 100644 --- a/kitchen/views_htmx.py +++ b/kitchen/views_htmx.py @@ -11,8 +11,12 @@ from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_POST, require_http_methods from .models import ( - Ingredient, PantryItem, MetaRecipe, Slot, SlotOption, - Recipe, CookLog, ShoppingListItem, + Ingredient, PantryItem, MetaRecipe, CookLog, ShoppingListItem, +) +from .helpers import ( + find_ingredient as _find_ingredient, + get_pantry_total as _get_pantry_total, + get_section_key as _get_section, ) @@ -38,25 +42,6 @@ def _pantry_context(): } -def _get_pantry_total(ingredient_id): - total = Decimal("0") - for item in PantryItem.objects.filter(ingredient_id=ingredient_id, quantity__gt=0): - total += item.quantity - return total - - -def _find_ingredient(name): - """Find ingredient by name or alias (case-insensitive).""" - try: - return Ingredient.objects.get(name__iexact=name) - except Ingredient.DoesNotExist: - pass - for ingredient in Ingredient.objects.all(): - if ingredient.aliases and any(a.lower() == name.lower() for a in ingredient.aliases): - return ingredient - return None - - # --- Page Views --- def pantry_page(request): @@ -164,13 +149,17 @@ def recipes_page(request): }) -def shopping_page(request): +def _shopping_list_items(): + """Fetch shopping list items annotated with their display section.""" items = ShoppingListItem.objects.select_related("ingredient").all() - # Add section info for item in items: item.section = _get_section_for_item(item) + return items + + +def shopping_page(request): return render(request, "kitchen/shopping.html", { - "items": items, + "items": _shopping_list_items(), "active_tab": "shopping", }) @@ -305,8 +294,6 @@ def pantry_cancel_edit(request): @require_POST def shopping_generate(request): """Generate smart shopping list and return updated HTML.""" - from .views import _get_section - staple_count = 0 expiring_count = 0 recipe_gap_count = 0 @@ -376,12 +363,10 @@ def shopping_generate(request): }, ) - items = ShoppingListItem.objects.select_related("ingredient").all() - for item in items: - item.section = _get_section_for_item(item) + items = _shopping_list_items() summary = { - "total": len(set(s["ingredient"] for s in suggestions)), + "total": len(seen), "staples": staple_count, "expiring": expiring_count, "recipe_gaps": recipe_gap_count, @@ -400,31 +385,27 @@ def shopping_toggle(request, item_id): item.checked = not item.checked item.save(update_fields=["checked"]) - items = ShoppingListItem.objects.select_related("ingredient").all() - for i in items: - i.section = _get_section_for_item(i) - return render(request, "kitchen/partials/shopping_list.html", {"items": items}) + return render(request, "kitchen/partials/shopping_list.html", {"items": _shopping_list_items()}) @csrf_exempt @require_POST def shopping_clear(request): ShoppingListItem.objects.filter(checked=True).delete() - items = ShoppingListItem.objects.select_related("ingredient").all() - for item in items: - item.section = _get_section_for_item(item) - return render(request, "kitchen/partials/shopping_list.html", {"items": items}) + return render(request, "kitchen/partials/shopping_list.html", {"items": _shopping_list_items()}) + + +_SECTION_LABELS = { + "protein": "Protein", + "veg": "Veg", + "carbs": "Carbs", + "dairy": "Dairy", + "other": "Other", +} def _get_section_for_item(item): + """Title-cased, template-facing section label for a ShoppingListItem.""" if item.ingredient: - tag_names = set(item.ingredient.tags.values_list("name", flat=True)) - if "protein" in tag_names: - return "Protein" - if "veg" in tag_names: - return "Veg" - if "carb" in tag_names: - return "Carbs" - if "dairy" in tag_names: - return "Dairy" + return _SECTION_LABELS[_get_section(item.ingredient)] return "Other" |
