Source badges on products: Магнит (red), 5ка (green), KDV (orange), ИОН (gray), Свой (yellow)

- 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)
This commit is contained in:
4aiman 2026-05-30 15:59:50 +03:00
commit 8d9b5aaf7e
3 changed files with 33 additions and 2 deletions

View file

@ -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);

View file

@ -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,

View file

@ -278,6 +278,7 @@ async function renderToday(container) {
`<li class="log-item food-edit-item${f.nutrients_guessed ? " guessed" : ""}" data-food-id="${f.id}">
<span class="log-time">${f.time ?? ""}</span>
<span class="log-desc">${esc(f.product_name ?? f.note ?? "—")}
${sourceBadge(f.product_source)}
${f.unit_amount && f.unit_short
? `<small>${f.unit_amount} ${f.unit_short}</small>`
: f.amount_g ? `<small>${f.amount_g}г</small>` : ""}
@ -1259,6 +1260,7 @@ async function renderProducts(container) {
${esc(p.name)}
${p.brand ? `<span class="prod-brand">${esc(p.brand)}</span>` : ""}
${p.weight_g ? `<span class="prod-weight">${p.weight_g}г</span>` : ""}
${sourceBadge(p.source)}
</div>
<div class="prod-card-kcal">${kcal != null ? kcal + " кк" : "?"}</div>
</div>
@ -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 `<span class="src-badge ${cls}">${label}</span>`;
}
function esc(str) {
return String(str ?? "")
.replace(/&/g, "&amp;").replace(/</g, "&lt;")