Coffee journaling on ATProto (alpha) alpha.arabica.social
coffee
17
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix: add details section when using recipe

authored by

Patrick Dewey and committed by tangled.org ba0181d2 1f42c3ea

+44
+5
internal/models/models.go
··· 202 202 } 203 203 204 204 // Interpolate fills in computed/derived fields from existing data. 205 + // - BrewerType from BrewerObj if not set 205 206 // - WaterAmount from sum of pours if not set 206 207 // - Ratio from water/coffee amounts 207 208 func (r *Recipe) Interpolate() { 209 + // Derive brewer type from joined brewer object if missing 210 + if r.BrewerType == "" && r.BrewerObj != nil && r.BrewerObj.BrewerType != "" { 211 + r.BrewerType = r.BrewerObj.BrewerType 212 + } 208 213 // Derive water amount from pours if missing 209 214 if r.WaterAmount == 0 && len(r.Pours) > 0 { 210 215 var total int
+28
internal/models/recipe_filter_test.go
··· 190 190 assert.Equal(t, 0.0, recipe.Ratio) // can't compute ratio without coffee 191 191 } 192 192 193 + func TestRecipeInterpolate_BrewerTypeFromObj(t *testing.T) { 194 + // When BrewerType is empty but BrewerObj has a type, Interpolate should populate it 195 + recipe := &Recipe{ 196 + Name: "V60 Recipe", 197 + BrewerObj: &Brewer{Name: "V60", BrewerType: BrewerTypePourover}, 198 + } 199 + recipe.Interpolate() 200 + assert.Equal(t, BrewerTypePourover, recipe.BrewerType) 201 + } 202 + 203 + func TestRecipeInterpolate_BrewerTypeAlreadySet(t *testing.T) { 204 + // When BrewerType is already set, Interpolate should not overwrite it 205 + recipe := &Recipe{ 206 + Name: "Espresso Recipe", 207 + BrewerType: BrewerTypeEspresso, 208 + BrewerObj: &Brewer{Name: "Gaggia", BrewerType: BrewerTypeOther}, 209 + } 210 + recipe.Interpolate() 211 + assert.Equal(t, BrewerTypeEspresso, recipe.BrewerType) 212 + } 213 + 214 + func TestRecipeInterpolate_NoBrewerObj(t *testing.T) { 215 + // When no BrewerObj, BrewerType should remain empty 216 + recipe := &Recipe{Name: "Basic Recipe"} 217 + recipe.Interpolate() 218 + assert.Equal(t, "", recipe.BrewerType) 219 + } 220 + 193 221 func TestMatchesFilter_InterpolatesWaterFromPours(t *testing.T) { 194 222 // Recipe with no water_amount but pours that sum to 250g 195 223 recipe := &Recipe{
+11
static/js/brew-form.js
··· 322 322 if (recipe.brewer_rkey) { 323 323 this.onBrewerChange(recipe.brewer_rkey); 324 324 } 325 + // Fallback: use recipe's brewer_type directly if category wasn't 326 + // resolved from the dropdown cache (e.g. cross-user recipe with no 327 + // local brewer match, or stale cache). 328 + if (!this.brewerCategory) { 329 + const recipeBrewerType = 330 + recipe.brewer_type || recipe.brewer_obj?.brewer_type || ""; 331 + if (recipeBrewerType) { 332 + this.brewerCategory = 333 + this.normalizeBrewerCategory(recipeBrewerType); 334 + } 335 + } 325 336 326 337 // Always reset pours, then apply recipe pours if present 327 338 this.pours =