From 8d9b5aaf7e4538b74684bb1d505d2040fbf6b1aa Mon Sep 17 00:00:00 2001 From: 4aiman Date: Sat, 30 May 2026 15:59:50 +0300 Subject: [PATCH] =?UTF-8?q?Source=20badges=20on=20products:=20=D0=9C=D0=B0?= =?UTF-8?q?=D0=B3=D0=BD=D0=B8=D1=82=20(red),=205=D0=BA=D0=B0=20(green),=20?= =?UTF-8?q?KDV=20(orange),=20=D0=98=D0=9E=D0=9D=20(gray),=20=D0=A1=D0=B2?= =?UTF-8?q?=D0=BE=D0=B9=20(yellow)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - sourceBadge() helper renders colored badge by source field - searchProducts SELECT now includes source column - getFoodForDate SELECT includes p.source as product_source - Badge shown on product cards in search and food log entries - CSS: .src-badge with per-source colors (pastel, dark-theme friendly) --- frontend/css/styles.css | 15 +++++++++++++++ frontend/js/db.js | 4 ++-- frontend/js/main.js | 16 ++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/frontend/css/styles.css b/frontend/css/styles.css index 0a0620e..c4636a4 100644 --- a/frontend/css/styles.css +++ b/frontend/css/styles.css @@ -1445,6 +1445,21 @@ select { } /* Per-food-item nutrient line */ +.src-badge { + display: inline-block; + font-size: 10px; + padding: 1px 5px; + border-radius: 3px; + vertical-align: middle; + margin-left: 4px; + font-weight: 600; +} +.src-magnit { background: rgba(229, 57, 53, 0.25); color: #ef5350; } +.src-5ka { background: rgba(129, 199, 132, 0.2); color: #a5d6a7; } +.src-kdv { background: rgba(255, 167, 38, 0.25); color: #ffb74d; } +.src-ion { background: rgba(158, 158, 158, 0.2); color: #9e9e9e; } +.src-manual { background: rgba(255, 235, 59, 0.2); color: #fff176; } + .food-nutrients { font-size: 11px; color: var(--muted); diff --git a/frontend/js/db.js b/frontend/js/db.js index bed3f25..5c25fdd 100644 --- a/frontend/js/db.js +++ b/frontend/js/db.js @@ -110,7 +110,7 @@ async function searchProducts(query, limit) { return select( `SELECT id, name, brand, category, weight_g, kcal_per_100g, protein_per_100g, fat_per_100g, carbs_per_100g, fiber_per_100g, - composition, nutrients_guessed, + composition, nutrients_guessed, source, vit_a_mcg, vit_c_mg, vit_b1_mg, vit_b2_mg, vit_b3_mg, vit_e_mg, calcium_mg, iron_mg, magnesium_mg, potassium_mg, sodium_mg, phosphorus_mg, carotene_mcg, selenium_mcg, zinc_mg, copper_mg, folate_mcg, @@ -359,7 +359,7 @@ async function addFoodFromRecipe(date, time, recipeId) { async function getFoodForDate(date) { return select( `SELECT fl.*, p.name as product_name, p.brand as product_brand, - COALESCE(p.nutrients_guessed, 0) as nutrients_guessed, + COALESCE(p.nutrients_guessed, 0) as nutrients_guessed, p.source as product_source, p.vit_a_mcg, p.vit_c_mg, p.vit_d_mcg, p.vit_e_mg, p.vit_k_mcg, p.vit_b1_mg, p.vit_b2_mg, p.vit_b3_mg, p.vit_b6_mg, p.vit_b12_mcg, p.folate_mcg, diff --git a/frontend/js/main.js b/frontend/js/main.js index c4fc121..91f141e 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -278,6 +278,7 @@ async function renderToday(container) { `
  • ${f.time ?? ""} ${esc(f.product_name ?? f.note ?? "—")} + ${sourceBadge(f.product_source)} ${f.unit_amount && f.unit_short ? `${f.unit_amount} ${f.unit_short}` : f.amount_g ? `${f.amount_g}г` : ""} @@ -1259,6 +1260,7 @@ async function renderProducts(container) { ${esc(p.name)} ${p.brand ? `${esc(p.brand)}` : ""} ${p.weight_g ? `${p.weight_g}г` : ""} + ${sourceBadge(p.source)}
    ${kcal != null ? kcal + " кк" : "?"}
    @@ -4481,6 +4483,20 @@ function pickFile(accept, callback, asBinary) { input.click(); } +function sourceBadge(source) { + const map = { + magnit: ["Магнит", "src-magnit"], + "5ka": ["5ка", "src-5ka"], + kdv: ["KDV", "src-kdv"], + ion: ["ИОН", "src-ion"], + manual: ["Свой", "src-manual"], + recipe_import: ["Импорт", "src-manual"], + }; + const [label, cls] = map[source] || ["", ""]; + if (!label) return ""; + return `${label}`; +} + function esc(str) { return String(str ?? "") .replace(/&/g, "&").replace(/