From 4ac65420b7e12b5cdd5e2334bd3c333f019d8572 Mon Sep 17 00:00:00 2001 From: Ionel Andrei Cataon Date: Wed, 18 Feb 2026 18:05:54 +0200 Subject: [PATCH] s --- .../src/main/webapp/index.html | 127 +++++++++--------- 1 file changed, 60 insertions(+), 67 deletions(-) diff --git a/proiect-nutritie-java/src/main/webapp/index.html b/proiect-nutritie-java/src/main/webapp/index.html index 80662bb..7a43622 100644 --- a/proiect-nutritie-java/src/main/webapp/index.html +++ b/proiect-nutritie-java/src/main/webapp/index.html @@ -3,7 +3,7 @@ - NutriAI Elite v26.3 + NutriAI Elite v26.5 - Professional Suite @@ -15,37 +15,35 @@ .main-wrapper { display: flex; height: 100dvh; flex-direction: row; } @media (max-width: 991px) { .main-wrapper { flex-direction: column; overflow-y: auto; height: auto; } - .sidebar { width: 360px !important; height: auto !important; border-right: none !important; margin: 0 auto; } - .chat-section { height: 700px !important; } + .sidebar { width: 100% !important; height: auto !important; border-right: none !important; } + .chat-section { height: 800px !important; } body { overflow-y: auto; } } - .sidebar { width: 360px; background: var(--sidebar); border-right: 1px solid rgba(255,255,255,0.1); padding: 1.5rem; overflow-y: auto; flex-shrink: 0; } + .sidebar { width: 380px; background: var(--sidebar); border-right: 1px solid rgba(255,255,255,0.1); padding: 1.5rem; overflow-y: auto; flex-shrink: 0; } .chat-section { flex-grow: 1; display: flex; flex-direction: column; background: rgba(0,0,0,0.2); position: relative; } .label-pro { color: var(--accent); font-weight: 800; font-size: 0.75rem; text-transform: uppercase; margin-bottom: 5px; display: block; } - .glass-input { background: #fff !important; color: #000 !important; border: 3px solid var(--primary) !important; border-radius: 8px; font-weight: 800 !important; height: 45px; } - .stat-panel { background: linear-gradient(145deg, var(--primary), #1e3a8a); border-radius: 15px; padding: 1.5rem; margin: 15px 0; text-align: center; box-shadow: 0 10px 20px rgba(0,0,0,0.3); } - .water-hub { background: rgba(59, 130, 246, 0.1); border: 2px solid var(--primary); border-radius: 15px; padding: 15px; margin: 10px 0; text-align: center; } - .macro-hub { background: rgba(255,255,255,0.05); border-radius: 20px; padding: 20px; margin-top: 10px; border: 1px solid rgba(255,255,255,0.1); } - .chat-container { flex-grow: 1; overflow-y: auto; padding: 1.5rem; display: flex; flex-direction: column; gap: 1rem; } - .msg { padding: 1.2rem; border-radius: 1rem; font-size: 1rem; max-width: 90%; color: #fff !important; line-height: 1.5; } - .ai { background: var(--card); border-left: 5px solid var(--primary); align-self: flex-start; box-shadow: 0 4px 15px rgba(0,0,0,0.2); } - .user { background: var(--primary); align-self: flex-end; box-shadow: 0 4px 15px rgba(59, 130, 246, 0.3); } - .top-ctrl { padding: 12px 20px; display: flex; justify-content: flex-end; gap: 10px; background: rgba(0,0,0,0.4); border-bottom: 1px solid rgba(255,255,255,0.1); } - .input-area { padding: 20px; background: var(--sidebar); border-top: 1px solid rgba(255,255,255,0.1); display: flex; gap: 12px; } - .btn-shop { background: #f59e0b; color: #000; font-weight: 800; border: none; border-radius: 10px; padding: 0 20px; transition: 0.2s; } - .btn-shop:hover { background: #d97706; transform: translateY(-2px); } - .btn-reset { background: rgba(239, 68, 68, 0.1); color: #fca5a5; border: 1px solid #ef4444; border-radius: 10px; padding: 12px; font-weight: 700; width: 100%; margin-top: 20px; transition: 0.2s; } - .btn-reset:hover { background: rgba(239, 68, 68, 0.2); } - table { width: 100%; border-collapse: collapse; margin: 15px 0; background: rgba(0,0,0,0.3); border-radius: 10px; overflow: hidden; } - th, td { border: 1px solid rgba(255,255,255,0.1); padding: 12px; text-align: left; } - th { background: rgba(59, 130, 246, 0.2); color: var(--accent); font-weight: 800; text-transform: uppercase; font-size: 0.75rem; } + .glass-input { background: #fff !important; color: #000 !important; border: 3px solid var(--primary) !important; border-radius: 10px; font-weight: 800 !important; height: 48px; } + .stat-panel { background: linear-gradient(145deg, var(--primary), #1e3a8a); border-radius: 20px; padding: 1.5rem; margin: 15px 0; text-align: center; box-shadow: 0 10px 30px rgba(0,0,0,0.4); border: 1px solid rgba(255,255,255,0.1); } + .water-hub { background: rgba(59, 130, 246, 0.1); border: 2px solid var(--primary); border-radius: 18px; padding: 15px; margin: 12px 0; text-align: center; } + .macro-hub { background: rgba(255,255,255,0.03); border-radius: 24px; padding: 20px; margin-top: 15px; border: 1px solid rgba(255,255,255,0.08); } + .chat-container { flex-grow: 1; overflow-y: auto; padding: 1.5rem; display: flex; flex-direction: column; gap: 1.2rem; } + .msg { padding: 1.2rem; border-radius: 1.2rem; font-size: 1rem; max-width: 92%; color: #fff !important; line-height: 1.6; } + .ai { background: var(--card); border-left: 6px solid var(--primary); align-self: flex-start; box-shadow: 0 5px 20px rgba(0,0,0,0.2); } + .user { background: var(--primary); align-self: flex-end; box-shadow: 0 5px 20px rgba(59, 130, 246, 0.2); } + .top-ctrl { padding: 15px 25px; display: flex; justify-content: flex-end; gap: 12px; background: rgba(0,0,0,0.5); border-bottom: 1px solid rgba(255,255,255,0.1); } + .input-area { padding: 25px; background: var(--sidebar); border-top: 1px solid rgba(255,255,255,0.1); display: flex; gap: 15px; } + .btn-shop { background: #f59e0b; color: #000; font-weight: 800; border: none; border-radius: 12px; padding: 0 25px; transition: 0.3s cubic-bezier(0.4, 0, 0.2, 1); } + .btn-reset { background: rgba(239, 68, 68, 0.1); color: #fca5a5; border: 1px solid #ef4444; border-radius: 12px; padding: 14px; font-weight: 700; width: 100%; margin-top: 25px; } + table { width: 100%; border-collapse: separate; border-spacing: 0; margin: 20px 0; background: rgba(0,0,0,0.3); border-radius: 12px; overflow: hidden; border: 1px solid rgba(255,255,255,0.1); } + th, td { padding: 14px; text-align: left; border-bottom: 1px solid rgba(255,255,255,0.05); } + th { background: rgba(59, 130, 246, 0.2); color: var(--accent); font-weight: 800; text-transform: uppercase; font-size: 0.7rem; letter-spacing: 1px; } - +

0

-

Daily Calorie Target

+

Target Calories

0.0L

- Daily Hydration + Daily Hydration
- -
-
P
0g
-
C
0g
-
F
0g
+ +
+
PROTEIN
0g
+
CARBS
0g
+
FATS
0g
- +
- - - + +
-
System Ready.
- The nutritional database has been audited. I have locked the caloric density of key ingredients (Brown Rice, Oats) to prevent math hallucinations. Please enter your biometrics to begin. +
Biometric Intelligence Active.
+ I am ready. Please fill in your data. I can now handle custom ingredient requests, high-protein focuses, and complex variety while maintaining strict caloric math.
- +
@@ -123,15 +120,17 @@ function setUnits(mode) { if((mode==='metric' && !isMetric) || (mode==='imperial' && isMetric)) { isMetric = !isMetric; - const w = document.getElementById('w'), t = document.getElementById('t'), h = document.getElementById('h'); - if(w.value) w.value = isMetric ? (w.value/2.205).toFixed(0) : (w.value*2.205).toFixed(0); - if(t.value) t.value = isMetric ? (t.value/2.205).toFixed(0) : (t.value*2.205).toFixed(0); - if(h.value) h.value = isMetric ? (h.value*2.54).toFixed(0) : (h.value/2.54).toFixed(0); + ['w','t'].forEach(id => { + let v = document.getElementById(id).value; + if(v) document.getElementById(id).value = isMetric ? (v/2.205).toFixed(1) : (v*2.205).toFixed(1); + }); + let hv = document.getElementById('h').value; + if(hv) document.getElementById('h').value = isMetric ? (hv*2.54).toFixed(0) : (hv/2.54).toFixed(1); document.getElementById('txtW').innerText = isMetric ? "Current (kg)" : "Current (lb)"; document.getElementById('txtT').innerText = isMetric ? "Target (kg)" : "Target (lb)"; document.getElementById('txtH').innerText = isMetric ? "Height (cm)" : "Height (in)"; - document.getElementById('btnMetric').className = isMetric ? "btn btn-primary active btn-sm px-3" : "btn btn-outline-primary btn-sm px-3"; - document.getElementById('btnImperial').className = !isMetric ? "btn btn-primary active btn-sm px-3" : "btn btn-outline-primary btn-sm px-3"; + document.getElementById('btnMetric').className = isMetric ? "btn btn-primary active btn-sm px-4" : "btn btn-outline-primary btn-sm px-4"; + document.getElementById('btnImperial').className = !isMetric ? "btn btn-primary active btn-sm px-4" : "btn btn-outline-primary btn-sm px-4"; update(); } } @@ -147,57 +146,51 @@ document.getElementById('kcal').innerText = total; document.getElementById('h2o').innerText = isMetric ? (wc * 0.035).toFixed(1) + "L" : (wv * 0.6).toFixed(0) + "oz"; document.getElementById('aggDisp').innerText = (agg>0?'+':'')+agg+" kcal"; - const pG = Math.round((total * 0.3)/4), cG = Math.round((total * 0.4)/4), fG = Math.round((total * 0.3)/9); - document.getElementById('pG').innerText = pG+"g"; document.getElementById('cG').innerText = cG+"g"; document.getElementById('fG').innerText = fG+"g"; + const pG = Math.round((total * 0.35)/4), cG = Math.round((total * 0.35)/4), fG = Math.round((total * 0.3)/9); + document.getElementById( 'pG' ).innerText = pG+"g"; document.getElementById( 'cG' ).innerText = cG+"g"; document.getElementById( 'fG' ).innerText = fG+"g"; if(mChart) { mChart.data.datasets[0].data = [pG*4, cG*4, fG*9]; mChart.update(); } } function resetAll() { - ['w','t','h','age','agg'].forEach(id => document.getElementById(id).value = id === 'agg' ? 0 : ""); + ['w','t','h','age','agg'].forEach(id => document.getElementById(id).value = id==='agg'?0:""); document.getElementById('act').selectedIndex = 0; document.getElementById('kcal').innerText = "0"; - document.getElementById('pG').innerText = "0g"; document.getElementById('cG').innerText = "0g"; document.getElementById('fG').innerText = "0g"; - document.getElementById('chat').innerHTML = `
System Reset Complete. Ready for new inputs.
`; - conversationHistory = []; - update(); + document.getElementById('chat').innerHTML = `
Reset successful. Standing by.
`; + conversationHistory = []; update(); } async function talk(custom) { const box = document.getElementById('chat'), input = document.getElementById('uIn'), targetKcal = document.getElementById('kcal').innerText; - const text = custom === 'GENERATE_SHOPPING_LIST' ? "Provide a full shopping list based on the plan above." : (custom || input.value); + const text = custom === 'GENERATE_SHOPPING_LIST' ? "Sum all ingredients from the plan into a weekly shopping list." : (custom || input.value); if(!text) return; if(!custom) { box.innerHTML += `
${text}
`; input.value=""; } - const id = 'ai-'+Date.now(); box.innerHTML += `
Auditing nutritional math...
`; + const id = 'ai-'+Date.now(); box.innerHTML += `
Generating meal architecture...
`; box.scrollTop = box.scrollHeight; - const sysPrompt = {role:"system", content: `Expert Dietitian. DAILY LIMIT: ${targetKcal} kcal. - STRICT MATH RULES (NO EXCEPTIONS): - - 100g RAW Brown Rice = 360-370 kcal. (NEVER 120 or 220). - - 100g RAW Oats = 380 kcal. - - 100g Chicken Breast = 165 kcal. - - You MUST double-check: Total Meal Kcal = Sum of ingredient Kcals. - - If you need fewer calories, DECREASE the grams. Do NOT change the caloric density. - - Output: Markdown tables with Weight (RAW), Calories, P, C, F.`}; + const sysPrompt = {role:"system", content: `Advanced Clinical Nutritionist. GOAL: EXACTLY ${targetKcal} kcal. + 1. MATH AUDIT: You MUST verify sums. 100g RAW Brown Rice = 360 kcal. 100g RAW Oats = 380 kcal. + 2. FOOD DIVERSITY: Use Steak, Salmon, Eggs, Avocado, Berries, Quinoa, Sweet Potato, Nut Butters. NEVER just chicken/rice unless asked. + 3. CUSTOMIZATION: If user asks for "Dense Protein" or "Specific Ingredients", prioritize those while scaling portions to hit ${targetKcal} kcal EXACTLY. + 4. STRUCTURE: Provide daily totals for P/C/F. Ensure Math checks: (P*4)+(C*4)+(F*9) = Total Kcal.`}; conversationHistory.push({role: "user", content: text}); try { const res = await fetch("https://api.groq.com/openai/v1/chat/completions", { method: "POST", headers: {"Content-Type":"application/json", "Authorization":`Bearer ${API}`}, - body: JSON.stringify({ model:"llama-3.3-70b-versatile", messages:[sysPrompt, ...conversationHistory], temperature: 0.0 }) + body: JSON.stringify({ model:"llama-3.3-70b-versatile", messages:[sysPrompt, ...conversationHistory], temperature: 0.2 }) }); const d = await res.json(); const aiMsg = d.choices[0].message.content; conversationHistory.push({role: "assistant", content: aiMsg}); document.getElementById(id).innerHTML = marked.parse(aiMsg); - } catch(e) { document.getElementById(id).innerText = "Connection error."; } + } catch(e) { document.getElementById(id).innerText = "API Error."; } box.scrollTop = box.scrollHeight; } window.onload = () => { mChart = new Chart(document.getElementById('mChart').getContext('2d'), { type: 'doughnut', data: { datasets: [{ data: [1,1,1], backgroundColor: ['#0dcaf0','#dc3545','#ffc107'], borderWeight:0 }] }, - options: { plugins: { legend: { display: false } }, cutout: '75%' } + options: { plugins: { legend: { display: false } }, cutout: '78%' } }); }