s
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
<title>NutriAI Elite v20.0</title>
|
<title>NutriAI Elite v21.0</title>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
@@ -57,13 +57,11 @@
|
|||||||
<div class="main-wrapper">
|
<div class="main-wrapper">
|
||||||
<div class="sidebar">
|
<div class="sidebar">
|
||||||
<h3 class="fw-extrabold mb-3"><i class="fas fa-bolt text-primary"></i> NUTRI ELITE</h3>
|
<h3 class="fw-extrabold mb-3"><i class="fas fa-bolt text-primary"></i> NUTRI ELITE</h3>
|
||||||
|
|
||||||
<div class="row g-2">
|
<div class="row g-2">
|
||||||
<div class="col-6"><label class="label-pro" id="txtW">Weight</label><input type="number" id="w" class="form-control glass-input" placeholder="--" oninput="update()"></div>
|
<div class="col-6"><label class="label-pro" id="txtW">Weight</label><input type="number" id="w" class="form-control glass-input" placeholder="--" oninput="update()"></div>
|
||||||
<div class="col-6"><label class="label-pro" id="txtT">Target</label><input type="number" id="t" class="form-control glass-input" placeholder="--" oninput="update()"></div>
|
<div class="col-6"><label class="label-pro" id="txtT">Target</label><input type="number" id="t" class="form-control glass-input" placeholder="--" oninput="update()"></div>
|
||||||
<div class="col-6"><label class="label-pro" id="txtH">Height</label><input type="number" id="h" class="form-control glass-input" placeholder="--" oninput="update()"></div>
|
<div class="col-6"><label class="label-pro" id="txtH">Height</label><input type="number" id="h" class="form-control glass-input" placeholder="--" oninput="update()"></div>
|
||||||
<div class="col-6"><label class="label-pro">Age</label><input type="number" id="age" class="form-control glass-input" placeholder="--" oninput="update()"></div>
|
<div class="col-6"><label class="label-pro">Age</label><input type="number" id="age" class="form-control glass-input" placeholder="--" oninput="update()"></div>
|
||||||
|
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label class="label-pro">Activity</label>
|
<label class="label-pro">Activity</label>
|
||||||
<select id="act" class="form-select glass-input" onchange="update()">
|
<select id="act" class="form-select glass-input" onchange="update()">
|
||||||
@@ -81,14 +79,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="stat-panel">
|
<div class="stat-panel"><h1 class="fw-bold mb-0" id="kcal">0</h1><p class="text-uppercase fw-bold m-0 opacity-75 small">Target Calories</p></div>
|
||||||
<h1 class="fw-bold mb-0" id="kcal">0</h1>
|
|
||||||
<p class="text-uppercase fw-bold m-0 opacity-75 small">Target Calories</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="water-hub">
|
<div class="water-hub">
|
||||||
<h2 class="fw-bold text-info mb-0" id="h2o">0.0L</h2>
|
<h2 class="fw-bold text-info mb-0" id="h2o">0.0L</h2>
|
||||||
<span class="label-pro"><i class="fas fa-droplet me-1"></i> Daily Hydration</span>
|
<span class="label-pro" id="txtH2O"><i class="fas fa-droplet me-1"></i> Daily Hydration</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="macro-hub">
|
<div class="macro-hub">
|
||||||
@@ -99,7 +94,6 @@
|
|||||||
<div class="col-4 text-warning">F: <span id="fG">0g</span></div>
|
<div class="col-4 text-warning">F: <span id="fG">0g</span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="btn-reset" onclick="resetAll()"><i class="fas fa-sync me-2"></i> RESET SYSTEM</button>
|
<button class="btn-reset" onclick="resetAll()"><i class="fas fa-sync me-2"></i> RESET SYSTEM</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -120,8 +114,8 @@
|
|||||||
|
|
||||||
<div id="chat" class="chat-container">
|
<div id="chat" class="chat-container">
|
||||||
<div class="msg ai shadow">
|
<div class="msg ai shadow">
|
||||||
<h5 class="fw-bold text-primary">System Unified.</h5>
|
<h5 class="fw-bold text-primary">Unit Sync Active.</h5>
|
||||||
Shopping list and Water tracker are back. All fields reset on load.
|
Raw ingredient weights and shopping list quantities will now match your **Metric/Imperial** selection.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -144,6 +138,23 @@
|
|||||||
|
|
||||||
function setTheme(t) { document.body.className = 'theme-' + t; }
|
function setTheme(t) { document.body.className = 'theme-' + t; }
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
document.getElementById('txtW').innerText = isMetric ? "Weight (kg)" : "Weight (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" : "btn btn-outline-primary btn-sm";
|
||||||
|
document.getElementById('btnImperial').className = !isMetric ? "btn btn-primary active btn-sm" : "btn btn-outline-primary btn-sm";
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function update() {
|
function update() {
|
||||||
const wv = parseFloat(document.getElementById('w').value)||0, hv = parseFloat(document.getElementById('h').value)||0;
|
const wv = parseFloat(document.getElementById('w').value)||0, hv = parseFloat(document.getElementById('h').value)||0;
|
||||||
const av = parseFloat(document.getElementById('age').value)||0, act = parseFloat(document.getElementById('act').value)||1;
|
const av = parseFloat(document.getElementById('age').value)||0, act = parseFloat(document.getElementById('act').value)||1;
|
||||||
@@ -155,7 +166,7 @@
|
|||||||
const total = Math.round((bmr * act) + agg);
|
const total = Math.round((bmr * act) + agg);
|
||||||
|
|
||||||
document.getElementById('kcal').innerText = total;
|
document.getElementById('kcal').innerText = total;
|
||||||
document.getElementById('h2o').innerText = (wc * 0.035).toFixed(1) + "L";
|
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";
|
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);
|
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";
|
document.getElementById('pG').innerText = pG+"g"; document.getElementById('cG').innerText = cG+"g"; document.getElementById('fG').innerText = fG+"g";
|
||||||
@@ -166,8 +177,8 @@
|
|||||||
['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('act').selectedIndex = 0;
|
||||||
document.getElementById('kcal').innerText = "0";
|
document.getElementById('kcal').innerText = "0";
|
||||||
document.getElementById('h2o').innerText = "0.0L";
|
document.getElementById('h2o').innerText = isMetric ? "0.0L" : "0oz";
|
||||||
document.getElementById('chat').innerHTML = `<div class="msg ai shadow">System reset. Ready for new inputs.</div>`;
|
document.getElementById('chat').innerHTML = `<div class="msg ai shadow">System reset. Unit system: ${isMetric?'Metric':'Imperial'}.</div>`;
|
||||||
if(mChart) { mChart.data.datasets[0].data = [1,1,1]; mChart.update(); }
|
if(mChart) { mChart.data.datasets[0].data = [1,1,1]; mChart.update(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,19 +186,19 @@
|
|||||||
const box = document.getElementById('chat'), input = document.getElementById('uIn');
|
const box = document.getElementById('chat'), input = document.getElementById('uIn');
|
||||||
const text = custom || input.value; if(!text) return;
|
const text = custom || input.value; if(!text) return;
|
||||||
if(!custom) { box.innerHTML += `<div class="msg user shadow-sm">${text}</div>`; input.value=""; }
|
if(!custom) { box.innerHTML += `<div class="msg user shadow-sm">${text}</div>`; input.value=""; }
|
||||||
const id = 'ai-'+Date.now(); box.innerHTML += `<div id="${id}" class="msg ai shadow">Processing...</div>`;
|
const id = 'ai-'+Date.now(); box.innerHTML += `<div id="${id}" class="msg ai shadow">Calculating with ${isMetric?'Metric':'Imperial'} units...</div>`;
|
||||||
box.scrollTop = box.scrollHeight;
|
box.scrollTop = box.scrollHeight;
|
||||||
try {
|
try {
|
||||||
const res = await fetch("https://api.groq.com/openai/v1/chat/completions", {
|
const res = await fetch("https://api.groq.com/openai/v1/chat/completions", {
|
||||||
method: "POST", headers: {"Content-Type":"application/json", "Authorization":`Bearer ${API}`},
|
method: "POST", headers: {"Content-Type":"application/json", "Authorization":`Bearer ${API}`},
|
||||||
body: JSON.stringify({ model:"llama-3.3-70b-versatile", messages:[
|
body: JSON.stringify({ model:"llama-3.3-70b-versatile", messages:[
|
||||||
{role:"system", content:`Pro Nutritionist. Target: ${document.getElementById('kcal').innerText} kcal. Use Markdown tables.`},
|
{role:"system", content: `Expert Nutritionist. Target: ${document.getElementById('kcal').innerText} kcal. SYSTEM: ${isMetric ? 'METRIC (grams, kg, liters)' : 'IMPERIAL (ounces, lbs, cups)'}. MANDATORY: Use raw weights for ALL ingredients. Provide shopping list quantities in ${isMetric ? 'grams/kilograms' : 'ounces/lbs'}. Use Markdown tables.`},
|
||||||
{role:"user", content:text}
|
{role:"user", content:text}
|
||||||
]})
|
]})
|
||||||
});
|
});
|
||||||
const d = await res.json();
|
const d = await res.json();
|
||||||
document.getElementById(id).innerHTML = marked.parse(d.choices[0].message.content);
|
document.getElementById(id).innerHTML = marked.parse(d.choices[0].message.content);
|
||||||
} catch(e) { document.getElementById(id).innerText = "Error connecting to coach."; }
|
} catch(e) { document.getElementById(id).innerText = "Error syncing with coach."; }
|
||||||
box.scrollTop = box.scrollHeight;
|
box.scrollTop = box.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user