s
This commit is contained in:
@@ -3,49 +3,51 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>NutriAI Elite - High Visibility Pro</title>
|
<title>NutriAI Elite v8.0 - Professional Nutritionist</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>
|
||||||
<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">
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;600;800&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--primary: #3b82f6;
|
--primary: #3b82f6;
|
||||||
--bg-dark: #020617;
|
--bg: #0f172a;
|
||||||
--card-dark: #1e293b;
|
--sidebar-bg: #1e293b;
|
||||||
--input-bg: #ffffff;
|
--input-bg: #ffffff; /* Stark white for input contrast */
|
||||||
--input-text: #020617;
|
--input-text: #000000; /* Deep black for input readability */
|
||||||
}
|
}
|
||||||
|
|
||||||
body { background-color: var(--bg-dark); color: #f8fafc; font-family: 'Outfit', sans-serif; transition: 0.3s; }
|
body { background-color: var(--bg); color: #ffffff; font-family: 'Outfit', sans-serif; transition: 0.4s; }
|
||||||
|
|
||||||
.sidebar { background: #0f172a; border-right: 1px solid #334155; min-height: 100vh; padding: 2rem; overflow-y: auto; }
|
/* Sidebar Styling */
|
||||||
|
.sidebar { background: var(--sidebar-bg); border-right: 1px solid rgba(255,255,255,0.1); min-height: 100vh; padding: 2rem; }
|
||||||
|
|
||||||
.label-bright { color: #3b82f6; font-weight: 700; font-size: 0.85rem; text-transform: uppercase; margin-bottom: 5px; display: block; }
|
/* High Contrast Labels and Inputs */
|
||||||
|
.label-pro { color: #60a5fa; font-weight: 800; font-size: 0.75rem; text-transform: uppercase; margin-bottom: 5px; display: block; }
|
||||||
.form-control, .form-select {
|
.glass-input {
|
||||||
background: var(--input-bg) !important;
|
background: var(--input-bg) !important;
|
||||||
color: var(--input-text) !important;
|
color: var(--input-text) !important;
|
||||||
border: 2px solid var(--primary) !important;
|
border: 2px solid var(--primary) !important;
|
||||||
font-weight: 700 !important;
|
border-radius: 8px; font-weight: 600 !important;
|
||||||
border-radius: 10px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calorie Hub */
|
||||||
.kcal-hub {
|
.kcal-hub {
|
||||||
background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%);
|
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
|
||||||
padding: 1.5rem; border-radius: 15px; border: 1px solid #60a5fa; margin-top: 20px;
|
border-radius: 15px; padding: 1.5rem; text-align: center; margin-top: 20px;
|
||||||
|
box-shadow: 0 10px 25px rgba(37, 99, 235, 0.3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-area { height: 60vh; overflow-y: auto; padding: 20px; background: rgba(0,0,0,0.3); border-radius: 20px; }
|
/* Chat Area & Markdown Tables */
|
||||||
|
.chat-area { height: 60vh; overflow-y: auto; padding: 25px; border-radius: 20px; background: rgba(0,0,0,0.2); }
|
||||||
.msg { padding: 1.5rem; border-radius: 15px; margin-bottom: 1.5rem; max-width: 95%; line-height: 1.6; }
|
.msg { padding: 1.5rem; border-radius: 1.2rem; margin-bottom: 1.5rem; max-width: 90%; line-height: 1.6; }
|
||||||
.ai { background: #1e293b; border: 1px solid #334155; color: #ffffff; }
|
.ai { background: #334155; border-left: 5px solid #3b82f6; color: #ffffff; }
|
||||||
.user { background: #10b981; margin-left: auto; color: white; font-weight: 600; }
|
.user { background: #10b981; margin-left: auto; color: white; font-weight: 600; }
|
||||||
|
|
||||||
table { width: 100%; border-collapse: collapse; margin: 15px 0; background: #0f172a; border-radius: 8px; overflow: hidden; }
|
/* Groq Professional Table Styling */
|
||||||
th, td { padding: 12px; border: 1px solid #334155; text-align: left; font-size: 0.95rem; }
|
table { width: 100%; margin: 15px 0; border-collapse: collapse; background: #0f172a; color: white; border-radius: 8px; overflow: hidden; }
|
||||||
th { background: #3b82f6; color: white; }
|
th, td { padding: 12px; border: 1px solid #334155; text-align: left; }
|
||||||
|
th { background: #3b82f6; }
|
||||||
|
|
||||||
.input-bar { background: #1e293b; border-radius: 50px; padding: 10px 25px; border: 2px solid var(--primary); }
|
.input-bar { background: #1e293b; border-radius: 50px; padding: 10px 25px; border: 2px solid var(--primary); }
|
||||||
#userInput { color: white !important; font-size: 1.1rem; }
|
#userInput { color: white !important; font-size: 1.1rem; }
|
||||||
@@ -56,54 +58,143 @@
|
|||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-3 sidebar">
|
<div class="col-lg-3 sidebar">
|
||||||
<h3 class="fw-bold mb-4 text-primary"><i class="fas fa-heartbeat me-2"></i>NutriAI Elite</h3>
|
<h3 class="fw-bold mb-4 text-primary"><i class="fas fa-dna me-2"></i>NutriAI <span class="text-white">Elite</span></h3>
|
||||||
|
|
||||||
<div class="row g-2 mb-3">
|
<div class="row g-3 mb-4">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<label class="label-bright">Current (kg)</label>
|
<label class="label-pro">Current (kg)</label>
|
||||||
<input type="number" id="weight" class="form-control" value="85" oninput="updateProfile()">
|
<input type="number" id="weight" class="form-control glass-input" value="85" oninput="updateProfile()">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<label class="label-bright">Target (kg)</label>
|
<label class="label-pro">Target (kg)</label>
|
||||||
<input type="number" id="targetWeight" class="form-control" value="75" oninput="updateProfile()">
|
<input type="number" id="targetW" class="form-control glass-input" value="75" oninput="updateProfile()">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<label class="label-bright">Height (cm)</label>
|
<label class="label-pro">Height (cm)</label>
|
||||||
<input type="number" id="height" class="form-control" value="180" oninput="updateProfile()">
|
<input type="number" id="height" class="form-control glass-input" value="180" oninput="updateProfile()">
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<label class="label-bright">Age</label>
|
<label class="label-pro">Age</label>
|
||||||
<input type="number" id="age" class="form-control" value="30" oninput="updateProfile()">
|
<input type="number" id="age" class="form-control glass-input" value="30" oninput="updateProfile()">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-12">
|
||||||
|
<label class="label-pro">Biological Sex</label>
|
||||||
<label class="label-bright">Biological Sex</label>
|
<select id="sex" class="form-select glass-input" onchange="updateProfile()">
|
||||||
<select id="sex" class="form-select mb-3" onchange="updateProfile()">
|
|
||||||
<option value="male">Male</option>
|
<option value="male">Male</option>
|
||||||
<option value="female">Female</option>
|
<option value="female">Female</option>
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
<label class="label-bright">Activity Level</label>
|
<div class="col-12">
|
||||||
<select id="activity" class="form-select mb-3" onchange="updateProfile()">
|
<label class="label-pro">Activity Level</label>
|
||||||
<option value="1.2">Sedentary (No Exercise)</option>
|
<select id="activity" class="form-select glass-input" onchange="updateProfile()">
|
||||||
<option value="1.375">Lightly Active (1-3 days)</option>
|
<option value="1.2">Sedentary (Office/No Exercise)</option>
|
||||||
<option value="1.55">Moderately Active (3-5 days)</option>
|
<option value="1.375">Light (1-2 days sport)</option>
|
||||||
|
<option value="1.55">Moderate (3-5 days sport)</option>
|
||||||
<option value="1.725">Very Active (Daily Heavy)</option>
|
<option value="1.725">Very Active (Daily Heavy)</option>
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
<label class="label-bright">Daily Deficit/Surplus</label>
|
<div class="col-12">
|
||||||
<select id="goalType" class="form-select mb-4" onchange="updateProfile()">
|
<label class="label-pro">Daily Deficit/Surplus</label>
|
||||||
<option value="-1000">Extreme Weight Loss (-1000 kcal)</option>
|
<select id="deficit" class="form-select glass-input" onchange="updateProfile()">
|
||||||
<option value="-500" selected>Steady Weight Loss (-500 kcal)</option>
|
<option value="-1000">Extreme Loss (-1000 kcal)</option>
|
||||||
<option value="0">Maintenance (Stay Same)</option>
|
<option value="-500" selected>Steady Loss (-500 kcal)</option>
|
||||||
<option value="300">Lean Bulk (+300 kcal)</option>
|
<option value="0">Maintenance</option>
|
||||||
<option value="500">Aggressive Bulk (+500 kcal)</option>
|
<option value="500">Mass Gain (+500 kcal)</option>
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
<div class="kcal-hub text-center shadow">
|
|
||||||
<small class="fw-bold text-uppercase opacity-75">Your Daily Goal</small>
|
|
||||||
<h1 class="display-5 fw-bold mb-0" id="totalKcal">0</h1>
|
|
||||||
<span class="small">CALORIES / DAY</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="mt-3 small text
|
<div class="kcal-hub shadow-lg">
|
||||||
|
<small class="text-uppercase fw-bold opacity-75">Your Calculated Goal</small>
|
||||||
|
<h1 class="fw-bold display-5 mb-0" id="totalKcal">2500</h1>
|
||||||
|
<span class="small fw-bold">KCAL / DAY</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="mt-3 small text-center opacity-50">Maintenance Level: <span id="maintVal">0</span> kcal</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-lg-9 p-5">
|
||||||
|
<h2 class="fw-bold mb-4">Elite AI Coaching Strategy</h2>
|
||||||
|
|
||||||
|
<div id="chatBox" class="chat-area shadow-inner">
|
||||||
|
<div class="msg ai shadow-sm">
|
||||||
|
<h5 class="fw-bold">Elite Protocol Ready.</h5>
|
||||||
|
I have synced your current data (<span class="text-info" id="curTag">85</span>kg) and target (<span class="text-info" id="tarTag">75</span>kg). <br>
|
||||||
|
<strong>How would you like to structure your diet today?</strong> Ask for a table-based meal plan.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-bar d-flex align-items-center mt-4">
|
||||||
|
<input type="text" id="userInput" class="form-control bg-transparent border-0 text-white"
|
||||||
|
placeholder="Message your coach (Press ENTER)...">
|
||||||
|
<button onclick="sendToGroq()" class="btn btn-primary rounded-circle p-3 ms-2" style="width: 55px; height: 55px;">
|
||||||
|
<i class="fas fa-paper-plane"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const GROQ_API_KEY = "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";
|
||||||
|
|
||||||
|
document.getElementById('userInput').addEventListener('keypress', (e) => { if(e.key === 'Enter') sendToGroq(); });
|
||||||
|
|
||||||
|
function updateProfile() {
|
||||||
|
const w = parseFloat(document.getElementById('weight').value) || 0;
|
||||||
|
const tw = parseFloat(document.getElementById('targetW').value) || 0;
|
||||||
|
const h = parseFloat(document.getElementById('height').value) || 0;
|
||||||
|
const a = parseFloat(document.getElementById('age').value) || 0;
|
||||||
|
const s = document.getElementById('sex').value;
|
||||||
|
const act = parseFloat(document.getElementById('activity').value);
|
||||||
|
const def = parseInt(document.getElementById('deficit').value);
|
||||||
|
|
||||||
|
// Mifflin-St Jeor Formula
|
||||||
|
let bmr = (s === 'male') ? (10 * w) + (6.25 * h) - (5 * a) + 5 : (10 * w) + (6.25 * h) - (5 * a) - 161;
|
||||||
|
let maintenance = Math.round(bmr * act);
|
||||||
|
let goal = maintenance + def;
|
||||||
|
|
||||||
|
document.getElementById('totalKcal').innerText = goal;
|
||||||
|
document.getElementById('maintVal').innerText = maintenance;
|
||||||
|
document.getElementById('curTag').innerText = w;
|
||||||
|
document.getElementById('tarTag').innerText = tw;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendToGroq() {
|
||||||
|
const input = document.getElementById('userInput');
|
||||||
|
const text = input.value.trim();
|
||||||
|
if(!text) return;
|
||||||
|
|
||||||
|
addMsg('user', text);
|
||||||
|
input.value = "";
|
||||||
|
const loadId = 'load-' + Date.now();
|
||||||
|
addMsg('ai', '<span class="spinner-grow spinner-grow-sm"></span> Analyzing data...', loadId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const resp = await fetch("https://api.groq.com/openai/v1/chat/completions", {
|
||||||
|
method: "POST", headers: { "Authorization": `Bearer ${GROQ_API_KEY}`, "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: "llama-3.3-70b-versatile",
|
||||||
|
messages: [
|
||||||
|
{ role: "system", content: `World-class Nutritionist. Goal: ${document.getElementById('totalKcal').innerText} kcal.
|
||||||
|
Target weight: ${document.getElementById('tarTag').innerText}kg.
|
||||||
|
STRICT RULE: Use Markdown TABLES for all meal plans and macro breakdowns. Use bold headers.` },
|
||||||
|
{ role: "user", content: text }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
});
|
||||||
|
const data = await resp.json();
|
||||||
|
// Use marked.js to render professional tables
|
||||||
|
document.getElementById(loadId).innerHTML = marked.parse(data.choices[0].message.content);
|
||||||
|
} catch(e) { document.getElementById(loadId).innerText = "API Error!"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
function addMsg(type, content, id = null) {
|
||||||
|
const b = document.getElementById('chatBox');
|
||||||
|
b.innerHTML += `<div class="msg ${type} shadow-sm" ${id ? `id="${id}"` : ''}>${content}</div>`;
|
||||||
|
b.scrollTop = b.scrollHeight;
|
||||||
|
}
|
||||||
|
updateProfile();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user