From de5cfd5c21e78b84a834e38d9846015e5cdad19f Mon Sep 17 00:00:00 2001 From: 4aiman Date: Fri, 29 May 2026 14:47:09 +0300 Subject: [PATCH] Manual KBJU input, omega-3/6/9, product micronutrients, nutrient strip expand MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Manual food entry: added B/Zh/U fields. Creates custom product in DB with user-provided KBJU, then logs it. Fixed addProduct lastInsertId. 2. Omega 3-6-9: columns in supplements, in supplement totals query, in MICRO_FIELDS form (34 fields total now). 3. Product card micronutrients: searchProducts now fetches all micro columns. renderProdDetails shows nutrient chips (sorted by deficiency) when product is expanded. 4. Supplement form: added B5, B7, chromium, manganese, molybdenum, iodine, phosphorus, omega-3/6/9, silicon, vanadium, lutein, lycopene. 5. Nutrient strip: tap to expand/collapse. Collapsed = 1 row (36px). Tap = toggle full view showing all nutrients. 6. Seed DB v6: added "Тесто для чебуреков 500г" (261 kcal, 7.1/3.8/48.2). --- frontend/css/styles.css | 5 ++ frontend/data/products_seed.db | Bin 8572928 -> 8572928 bytes frontend/js/db.js | 15 ++++- frontend/js/main.js | 107 +++++++++++++++++++++++++-------- 4 files changed, 99 insertions(+), 28 deletions(-) diff --git a/frontend/css/styles.css b/frontend/css/styles.css index c511f76..b3e822f 100644 --- a/frontend/css/styles.css +++ b/frontend/css/styles.css @@ -1452,6 +1452,11 @@ select { flex-wrap: wrap; gap: 6px; padding: 8px 14px; + cursor: pointer; +} +.nutrient-strip.nutrient-collapsed { + max-height: 36px; + overflow: hidden; } .nut-item { font-size: 12px; diff --git a/frontend/data/products_seed.db b/frontend/data/products_seed.db index 1bea9cacc1a5ae8eb05557e2f13a1055f0297052..66145d6b9d75658dee97012e3de2dd42d8ab103b 100644 GIT binary patch delta 616 zcmaLPH&4_70EY29gaauDSV0bX>|(`&UBSbGz4yjhumM(Vs2q?y43dbG(M6*PlM5=6 zXu{0+zu8Y<`~r^tqbA11H~Hn=p7iS{+38S!MRfF8q9Hmu*z~F@8tX=)k|kp#TXG~O zxsoSiC0`1pP>Lij#Zn@rGETNf#K4i z^K1U|{zTSrXII&`>O?A%l^ZTn9!W+1U0(1e7|L{Ix`PpdkHMGBQ!>55P%xP3$)v;o z9E=3-sjaCAK16fs6V1O?AOG`>Pql=tzs1V`CVP{89ifMzN1?}| P&QLnkHJt409%=Xqzn9kD delta 461 zcmWN}$vcz*0D$p6&9pE>5-p~@MNx?qB_*0^L7VoXGM3V!h*GEwhqnUpLf_$c{bhd5MKYm<(qL^dkqXvU(m%_B=qwUQj%=2QL}iO?m2I+JawSh< z5|?}_kR4JeJEcf=NwJj3ZrLMyWuKHvLiWo6DULfyp}ieR)*xAyq94a zkqVU0O)w)c;7% XPldjQzJ

Нутриенты

-
+
@@ -430,6 +430,8 @@ async function renderToday(container) { const nutrients = calcDailyNutrients(food, suppTotals); dailyNutEl.innerHTML = renderNutrientChips(nutrients) || `
нет данных о нутриентах
`; + // Tap to expand/collapse + dailyNutEl.onclick = () => dailyNutEl.classList.toggle("nutrient-collapsed"); } container.querySelector("#add-weight-btn").onclick = () => showWeightModal(); @@ -893,11 +895,25 @@ function showFoodModal() {
- +
- - + + +
+
+
+ + +
+
+ + +
+
+ + +
@@ -925,9 +941,22 @@ function showFoodModal() { await DB.addFoodEntry(state.date, time, selectedProduct.id, amountG, null, unitId, unitAmount); } else { const desc = overlay.querySelector("#m-desc").value.trim(); - const kcal = parseFloat(overlay.querySelector("#m-kcal").value) || null; if (!desc) return false; - await DB.addFoodManual(state.date, time, desc, kcal); + const kcal = parseFloat(overlay.querySelector("#m-kcal").value) || null; + const protein = parseFloat(overlay.querySelector("#m-protein").value) || null; + const fat = parseFloat(overlay.querySelector("#m-fat").value) || null; + const carbs = parseFloat(overlay.querySelector("#m-carbs").value) || null; + const amount = rawAmount; + if (kcal || protein || fat || carbs) { + // Create a custom product in DB, then log it + const pid = await DB.addProduct({ + name: desc, kcal_per_100g: kcal, protein_per_100g: protein, + fat_per_100g: fat, carbs_per_100g: carbs, source: "manual", + }); + await DB.addFoodEntry(state.date, time, pid, amount, null); + } else { + await DB.addFoodManual(state.date, time, desc, kcal); + } } }); @@ -1242,6 +1271,18 @@ async function renderProducts(container) { function renderProdDetails(p) { const r = v => v != null ? v : "—"; + // Micronutrient chips for this product (per 100g) + const RDI = BMR.RDI; + const microChips = []; + for (const [key, rdi] of Object.entries(RDI)) { + if (!p[key]) continue; + const pct = Math.round(p[key] / rdi * 100); + if (pct < 1) continue; + const label = NUTRIENT_LABELS[key] || key; + const cls = pct < 30 ? "nut-low" : pct < 80 ? "nut-mid" : "nut-ok"; + microChips.push({ pct, html: `
${label} ${pct}%
` }); + } + microChips.sort((a, b) => a.pct - b.pct); return `
@@ -1250,6 +1291,7 @@ async function renderProducts(container) {
${r(p.carbs_per_100g)}У
${r(p.fiber_per_100g)}Кл
+ ${microChips.length ? `
${microChips.map(c => c.html).join("")}
` : ""} ${p.composition ? `
${esc(p.composition)}
` : ""}
`; @@ -3245,25 +3287,40 @@ async function showLogSupplementModal() { // --------------------------------------------------------------------------- const MICRO_FIELDS = [ - { key: "vit_a_mcg", label: "Вит A (мкг)" }, - { key: "vit_c_mg", label: "Вит C (мг)" }, - { key: "vit_d_mcg", label: "Вит D (мкг)" }, - { key: "vit_e_mg", label: "Вит E (мг)" }, - { key: "vit_k_mcg", label: "Вит K (мкг)" }, - { key: "vit_b1_mg", label: "B1 (мг)" }, - { key: "vit_b2_mg", label: "B2 (мг)" }, - { key: "vit_b3_mg", label: "B3 (мг)" }, - { key: "vit_b6_mg", label: "B6 (мг)" }, - { key: "vit_b12_mcg", label: "B12 (мкг)" }, - { key: "folate_mcg", label: "Фолат (мкг)" }, - { key: "calcium_mg", label: "Ca (мг)" }, - { key: "iron_mg", label: "Fe (мг)" }, - { key: "magnesium_mg", label: "Mg (мг)" }, - { key: "zinc_mg", label: "Zn (мг)" }, - { key: "copper_mg", label: "Cu (мг)" }, - { key: "selenium_mcg", label: "Se (мкг)" }, - { key: "potassium_mg", label: "K (мг)" }, - { key: "sodium_mg", label: "Na (мг)" }, + { key: "vit_a_mcg", label: "Вит A (мкг РЭ)" }, + { key: "vit_c_mg", label: "Вит C (мг)" }, + { key: "vit_d_mcg", label: "Вит D3 (мкг)" }, + { key: "vit_e_mg", label: "Вит E (мг ТЭ)" }, + { key: "vit_k_mcg", label: "Вит K (мкг)" }, + { key: "vit_b1_mg", label: "B1 (мг)" }, + { key: "vit_b2_mg", label: "B2 (мг)" }, + { key: "vit_b3_mg", label: "B3/PP (мг)" }, + { key: "vit_b5_mg", label: "B5 (мг)" }, + { key: "vit_b6_mg", label: "B6 (мг)" }, + { key: "vit_b7_mcg", label: "B7/биотин (мкг)" }, + { key: "folate_mcg", label: "B9/фолат (мкг)" }, + { key: "vit_b12_mcg", label: "B12 (мкг)" }, + { key: "calcium_mg", label: "Ca (мг)" }, + { key: "magnesium_mg", label: "Mg (мг)" }, + { key: "iron_mg", label: "Fe (мг)" }, + { key: "zinc_mg", label: "Zn (мг)" }, + { key: "copper_mg", label: "Cu (мг)" }, + { key: "selenium_mcg", label: "Se (мкг)" }, + { key: "potassium_mg", label: "K (мг)" }, + { key: "sodium_mg", label: "Na (мг)" }, + { key: "phosphorus_mg", label: "P (мг)" }, + { key: "iodine_mg", label: "Йод (мг)" }, + { key: "chromium_mg", label: "Хром (мг)" }, + { key: "manganese_mg", label: "Mn (мг)" }, + { key: "molybdenum_mcg", label: "Mo (мкг)" }, + { key: "carotene_mcg", label: "b-каротин (мкг)" }, + { key: "omega3_mg", label: "Омега-3 (мг)" }, + { key: "omega6_mg", label: "Омега-6 (мг)" }, + { key: "omega9_mg", label: "Омега-9 (мг)" }, + { key: "silicon_mg", label: "Кремний (мг)" }, + { key: "vanadium_mg", label: "Ванадий (мг)" }, + { key: "lutein_mg", label: "Лютеин (мг)" }, + { key: "lycopene_mg", label: "Ликопин (мг)" }, ]; async function renderSupplements(container) {