nutritionDefaultsMerge.ts
3.16 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/**
* 将管理端保存的营养成分默认值 JSON 合并进 NUTRITION 元素 config(与 Web nutritionManualEntry 字段一致)。
* `<` 前缀由模板 config 决定,录入 JSON 不包含 LessThan 字段。
*/
import { NUTRITION_FACTS_LAYOUT_ROWS } from '../nutritionFactsLayout'
function fixedLabelForKey(key: string): string {
const hit = NUTRITION_FACTS_LAYOUT_ROWS.find((x) => x.key === key)
return hit?.label ?? key
}
function pickManual(manual: Record<string, string>, subKey: string): string {
return String(manual[subKey] ?? '').trim()
}
export function applyNutritionDefaultJsonToConfig(
baseCfg: Record<string, unknown>,
jsonStr: string,
): Record<string, unknown> {
const t = String(jsonStr ?? '').trim()
if (!t.startsWith('{')) return baseCfg
let manual: Record<string, string> = {}
try {
manual = JSON.parse(t) as Record<string, string>
} catch {
return baseCfg
}
const out: Record<string, unknown> = { ...baseCfg }
const baseFixed = Array.isArray(baseCfg.fixedNutrients)
? (baseCfg.fixedNutrients as Record<string, unknown>[])
: []
const cal = pickManual(manual, 'calories')
if (cal) out.calories = cal
else {
delete out.calories
delete out.Calories
}
out.servingsPerContainer = pickManual(manual, 'servingsPerContainer')
out.servingSize = pickManual(manual, 'servingSize')
const keysInOrder = [...NUTRITION_FACTS_LAYOUT_ROWS.map((r) => r.key)]
for (const row of baseFixed) {
const key = String(row.key ?? '').trim()
if (key && !keysInOrder.includes(key)) keysInOrder.push(key)
}
const fixedArr: Record<string, unknown>[] = []
for (const key of keysInOrder) {
const baseRow = baseFixed.find((r) => String(r.key ?? '').trim() === key)
const layout = NUTRITION_FACTS_LAYOUT_ROWS.find((r) => r.key === key)
const v = pickManual(manual, key)
const pct = pickManual(manual, `${key}Percent`)
const lessThan = Boolean(baseRow?.lessThan ?? baseCfg[`${key}LessThan`])
const label = String(baseRow?.label ?? layout?.label ?? fixedLabelForKey(key))
fixedArr.push({
key,
label,
value: v,
unit: '',
dailyValuePercent: pct,
lessThan,
})
if (v) out[key] = v
else delete out[key]
delete out[`${key}Unit`]
out[`${key}Percent`] = pct
out[`${key}LessThan`] = lessThan
}
out.fixedNutrients = fixedArr
const newExtras: Array<{ id: string; name: string; value: string; unit: string }> = []
for (const k of Object.keys(manual)) {
if (!k.startsWith('extra:') || !k.endsWith(':value')) continue
const id = k.slice('extra:'.length, -':value'.length)
newExtras.push({
id,
name: String(
(Array.isArray(out.extraNutrients)
? (out.extraNutrients as Record<string, unknown>[]).find((row) => String(row.id ?? '') === id)
: undefined)?.name ?? 'Other',
),
value: pickManual(manual, k),
unit: '',
})
out[`extra:${id}:percent`] = pickManual(manual, `extra:${id}:percent`)
out[`extra:${id}:lessThan`] = Boolean(baseCfg[`extra:${id}:lessThan`])
}
if (newExtras.length > 0) out.extraNutrients = newExtras
delete out.ingredientsText
delete out.IngredientsText
return out
}