From f871e5bb28be07ebf9996898ba73f5f6c46b779d Mon Sep 17 00:00:00 2001 From: 4aiman Date: Fri, 29 May 2026 18:21:49 +0300 Subject: [PATCH] Add custom product with full nutrients, bigger + buttons with border Custom product: - "+" button next to search on Products tab - showAddProductModal: name, KBJU, + all MICRO_FIELDS (34 nutrient fields) - All optional except name - Creates product with source="manual" - Refreshes search after save Button style: - .add-btn: 0.5px border with primary color, rounded corners (6px) - Min 40x36px for finger-friendly tapping on retina - Flexbox centered content --- frontend/css/styles.css | 10 +++++-- frontend/js/main.js | 66 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/frontend/css/styles.css b/frontend/css/styles.css index 69863f9..cc96e1a 100644 --- a/frontend/css/styles.css +++ b/frontend/css/styles.css @@ -478,12 +478,18 @@ select { .add-btn { background: none; - border: none; + border: 0.5px solid var(--primary); + border-radius: 6px; color: var(--primary); font-size: 22px; line-height: 1; cursor: pointer; - padding: 0 4px; + padding: 4px 10px; + min-width: 40px; + min-height: 36px; + display: flex; + align-items: center; + justify-content: center; } .log-list { diff --git a/frontend/js/main.js b/frontend/js/main.js index e7a54ae..eb272b0 100644 --- a/frontend/js/main.js +++ b/frontend/js/main.js @@ -1197,8 +1197,11 @@ async function renderProducts(container) {
- +
+ + +
@@ -1339,6 +1342,65 @@ async function renderProducts(container) { listEl.innerHTML = `
Введите название продукта
`; input.focus(); + + // Add custom product button + const addCustomBtn = container.querySelector("#add-custom-product"); + if (addCustomBtn) addCustomBtn.onclick = () => showAddProductModal(() => doSearch(true)); +} + +function showAddProductModal(onSaved) { + const microHtml = MICRO_FIELDS.map(f => { + return `
+ + +
`; + }).join(""); + + showModal(` +

Новый продукт

+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+

Нутриенты на 100г (опционально):

+
${microHtml}
`, + async overlay => { + const name = overlay.querySelector("#np-name").value.trim(); + if (!name) return false; + const data = { + name, + kcal_per_100g: parseFloat(overlay.querySelector("#np-kcal").value) || null, + protein_per_100g: parseFloat(overlay.querySelector("#np-protein").value) || null, + fat_per_100g: parseFloat(overlay.querySelector("#np-fat").value) || null, + carbs_per_100g: parseFloat(overlay.querySelector("#np-carbs").value) || null, + source: "manual", + }; + for (const f of MICRO_FIELDS) { + let val = parseFloat(overlay.querySelector(`#np-${f.key}`).value) || null; + if (val && f.mult) val *= f.mult; + data[f.key] = val; + } + await DB.addProduct(data); + if (onSaved) onSaved(); + }); } // ---------------------------------------------------------------------------