Skip to content

feat: unit-aware ingredient quantities in recipes - #182

Merged
johncarmack1984 merged 1 commit into
mainfrom
feat/ingredient-units
Jul 23, 2026
Merged

feat: unit-aware ingredient quantities in recipes#182
johncarmack1984 merged 1 commit into
mainfrom
feat/ingredient-units

Conversation

@johncarmack1984

@johncarmack1984 johncarmack1984 commented Jul 23, 2026

Copy link
Copy Markdown
Member

Product feedback (7/23): recipes force grams and produce nonsense — "1 g Rudi's Whole Wheat Bun".

The recipe editor spoke only grams and prefilled a new line with the ingredient's serving grams shown as grams. Nutrition math was always fine (everything is canonical grams); the gap was the entry/display unit.

Model — the ingredient's serving IS its count unit

The amounts table already carries unit / amount (count) / grams (canonical) / preferred. Grams stays the single source of truth for all nutrition math, so units are a pure display/entry layer.

  • An ingredient can name its serving unit ("bun", "slice", "patty", "each"; default "serving"), stored on the existing serving amount — no schema change. The ingredient form gains the field.
  • Recipe lines get a unit dropdown: the ingredient's count unit (its serving) + universal mass units (g, oz). A new line defaults to "1 " when a serving is declared, else 100 g. The client computes grams = count × factor; nutrition math is untouched.
  • Lines persist count + unit + preferred, so the detail reads "2 buns" and the form reloads in the same units. The content pull carries the count, so the local-first desktop shows the author's units after a sync (the web reads the server directly).

Migration decision (existing rows — documented, not reinterpreted)

Existing lines were stored with amount == grams, a "g" label, preferred = 'grams'. They render exactly as before — as grams. We do NOT retro-guess that a stored "1 g" meant "1 unit" (no reliable signal; silently rescaling would corrupt real gram amounts). Only new/edited lines use the count model — re-editing a line lets you switch it to a count unit.

Scope

Shipped: serving-unit data model + ingredient-form field + unit-aware recipe form + storage + recipe-detail display + content-pull fidelity. Deferred (documented, non-regressions — they stay grams, which is correct): the inline detail-editor's in-place amount scrubbing and the log add-flow keep gram entry; both can adopt the same picker next.

Verification

  • Full just check green — lint, typecheck, web tests, web + desktop builds, all Rust tests, schema-parity + bindings drift.
  • Live round-trip against a throwaway-DB server: create an ingredient with a "bun" serving unit (52 g) + a recipe of "2 bun", then confirm the detail (amount 2 / unit bun / grams 104), the edit reload (preferred: units), and the content pull (amount: 2) all carry the count with correct grams.

Recipes forced grams and prefilled a new line with the ingredient's
serving grams shown AS grams, so a bun read "1 g Rudi's Whole Wheat Bun"
instead of "1 bun".

- An ingredient can name its serving's unit ("bun", "slice", "patty",
  "each"; default "serving"), stored on the existing serving amount — no
  schema change. The ingredient form gains the field.
- Recipe form lines get a unit dropdown: the ingredient's count unit
  (its serving) plus universal mass units (g, oz). A new line defaults to
  "1 <serving-unit>" when a serving is declared, else 100 g. The client
  computes canonical grams = count × the unit's factor; all nutrition
  math still reads only grams, so it is unchanged.
- Lines store the count + unit + preferred alongside grams, so the recipe
  detail reads "2 buns" and the form reloads in the same units. The
  content pull carries the count too, so the local-first desktop shows
  the author's units after a sync.
- Existing rows are read exactly as before — as grams (amount mirrors
  grams, "grams" preferred). We do not retro-guess that a stored "1 g"
  meant "1 unit"; only new/edited lines use the count model.

Verified: full `just check` green; a live round-trip creates an
ingredient with a "bun" serving unit and a recipe of "2 bun", then
confirms the detail (2 bun / 104 g), the edit reload (units-preferred),
and the content pull all carry the count with correct grams.
@johncarmack1984
johncarmack1984 merged commit be8ac93 into main Jul 23, 2026
8 checks passed
@johncarmack1984
johncarmack1984 deleted the feat/ingredient-units branch July 23, 2026 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant