{'heading': 'How Pantry Storage (`StorageListView`) works in the app', 'summary': 'In `Ayurveda & Asana Yoga`, the `Storage` view tracks your real kitchen inventory by profile (`StorageItem`), holding one or more dated `Batch` records (`quantity` and optional `expirationDate`) per food. Tapping any stored food opens `StorageItemDetailView`, a draggable sheet with three segmented tabs: `Consume` (deduct used stock quickly), `Edit Batches` (add, adjust, or update batch expiration dates), and `History` (view every `StorageTransaction` in reverse chronological order).', 'bullets': ['Three segmented detail tabs: `Consume` (`minus.circle.fill`), `Edit Batches` (`pencil.circle.fill`), and `History` (`list.bullet.rectangle.portrait.fill`).', 'Earliest-expiration visibility: Each `StorageItem` computes `totalQuantity` across all batches and surfaces `firstExpirationDate` (`batches.compactMap { $0.expirationDate }.min()`) so older stock is used first.', 'Automatic batch consolidation: On appear, `viewModel.triggerConsolidationIfNeeded()` tidies redundant batch entries.', 'Unit-aware display: `TransactionHistoryContent` formats `Available Quantity` automatically into grams or ounces (`UnitConversion.formatGramsToGramsOrOunces`).']}
In `Ayurveda & Asana Yoga`, the `Storage` view tracks your real kitchen inventory by profile (`StorageItem`), holding one or more dated `Batch` records (`quantity` and optional `expirationDate`) per food. Tapping any stored food opens `StorageItemDetailView`, a draggable sheet with three segmented tabs: `Consume` (deduct used stock quickly), `Edit Batches` (add, adjust, or update batch expiration dates), and `History` (view every `StorageTransaction` in reverse chronological order).
Three segmented detail tabs: `Consume` (`minus.circle.fill`), `Edit Batches` (`pencil.circle.fill`), and `History` (`list.bullet.rectangle.portrait.fill`).
Earliest-expiration visibility: Each `StorageItem` computes `totalQuantity` across all batches and surfaces `firstExpirationDate` (`batches.compactMap { $0.expirationDate }.min()`) so older stock is used first.
Automatic batch consolidation: On appear, `viewModel.triggerConsolidationIfNeeded()` tidies redundant batch entries.
Unit-aware display: `TransactionHistoryContent` formats `Available Quantity` automatically into grams or ounces (`UnitConversion.formatGramsToGramsOrOunces`).
Adding Pantry Items and Why Storage Uses Batches
In a real kitchen, you rarely finish every last gram of basmati rice, mung dal, or ghee before buying a new bag or jar. If an inventory tracker stored only a single quantity and a single expiration date per ingredient, adding a fresh 1,000-gram bag of lentils would overwrite the expiration date of the 250 grams still sitting in your jar from three months ago.
To solve that, `StorageItem` in `Ayurveda & Asana Yoga` has a one-to-many relationship with `Batch` (`@Relationship(deleteRule: .cascade) var batches: [Batch]`). When you tap the floating add button in `StorageListView` to open `StorageEditorView`, you can record separate batches with their own `quantity` and `expirationDate`. The parent `StorageItem` automatically sums `totalQuantity` (`batches.reduce(0) { $0 + $1.quantity }`) and highlights `firstExpirationDate`—the earliest expiration date among your active batches—so you always know when the oldest batch needs to be cooked.
- One food row, multiple batches: Keep your pantry list uncluttered while preserving separate expiration dates for older and newer packages.
- Search your pantry instantly: Typing into the global search bar updates `viewModel.searchText` and filters your stored foods in real time.
- Automatic cleanup: Whenever `StorageListView` appears, `viewModel.triggerConsolidationIfNeeded()` consolidates compatible batches.
Using the Three Detail Tabs: "Consume", "Edit Batches", and "History"
Tapping any food row in `StorageListView` slides up `StorageItemDetailView` inside a `DraggableMenuView` with a `WrappingSegmentedControl` offering three tabs: `Consume`, `Edit Batches`, and `History`.
The first tab, `Consume` (`ConsumeStockViewContent`), is built for speed when you cook without logging a full calendar meal—or when you share or discard a portion of an ingredient: enter the amount used and tap to call `viewModel.consume(quantity: quantity, from: item)`. The second tab, `Edit Batches` (`StorageBatchEditorContent`), lets you inspect each individual `Batch`, correct a weight after a pantry audit, or update an expiration date. The third tab, `History` (`TransactionHistoryContent`), displays a `Current Status` card with `Available Quantity` followed by a reverse-chronological list of every `StorageTransaction` recorded for that food and profile.
- `Consume` tab: Deducts a specified quantity directly from your stored stock and closes the sheet cleanly.
- `Edit Batches` tab: Modify individual batch weights or expiration dates when reorganizing shelves.
- `History` tab: Audits every addition, meal-log deduction (`MealLogStorageLink`), and manual adjustment sorted by `StorageTransaction.date` (newest first).
How Meal Logs and Shopping Lists Connect to Pantry Storage
Your pantry storage does not live in a silo—it connects to both your daily meal log and your shopping lists. When you log a meal on your calendar that draws from stored ingredients, `MealLogStorageLink` records the exact `deductedGrams` link between the meal entry and the `StorageItem` so editing or removing a meal does not corrupt your inventory math.
And when you check off items in `ShoppingListModel` or review low-stock staples before a grocery trip, checking `Available Quantity` in `Storage` prevents buying duplicate bags of spices, flours, or pulses you already have on the shelf.
- Safe deletion confirmation: Swiping or tapping delete on a `StorageItem` prompts *"Are you sure you want to delete '<food name>' from your storage? This action cannot be undone."* before removing the item.
- Catalog + user food support: `TransactionHistoryContent` matches both `transaction.persistedFood?.id == foodID` and `transaction.catalogFoodID == foodID` so history works seamlessly across bundled and custom foods.
- Monthly 5-minute shelf check: Open `Storage`, sort mentally by `firstExpirationDate`, and use `Edit Batches` to reconcile any unlogged nibbles or spills.
Frequently Asked Questions
What happens when I have two batches of the same food with different expiration dates and I use the Consume tab?
`StorageItem` tracks each batch's expiration date and surfaces `firstExpirationDate` (`batches.compactMap { $0.expirationDate }.min()`), deducting consumed stock in first-expiring / first-in order while recording a `StorageTransaction` in the `History` tab.
Where can I see why my stored quantity of rice or dal decreased?
Tap the item in `Storage` and select the `History` tab (`TransactionHistoryContent`); every addition and deduction (`StorageTransaction`) is listed with its date and quantity from newest to oldest.
Does deleting a StorageItem delete the food itself from the app's food catalog?
No. Deleting an item in `StorageListView` only removes your profile's `StorageItem` inventory record and its batches; the underlying catalog or custom `FoodItem` remains intact.





