This commit is contained in:
Ionel Andrei Cataon
2026-02-18 16:24:17 +02:00
parent 4cce5acf2d
commit 9c4795741b

View File

@@ -3,204 +3,133 @@
<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 Ultra - Elite Coaching</title> <title>NutriAI Elite v4.0</title>
<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=Poppins:wght@300;400;600;700&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 {
--bg-dark: #0f172a; --primary: #3b82f6; --bg: #0f172a; --card: #1e293b; --text: #f8fafc;
--card-bg: #1e293b;
--accent-green: #10b981;
--accent-blue: #3b82f6;
--text-main: #f8fafc;
--text-muted: #94a3b8;
} }
/* Teme de culoare */
body.light-theme { --bg: #f1f5f9; --card: #ffffff; --text: #1e293b; }
body.blue-theme { --bg: #1e3a8a; --card: #1e40af; --text: #ffffff; }
body { body {
background-color: var(--bg-dark); background-color: var(--bg); color: var(--text);
font-family: 'Poppins', sans-serif; font-family: 'Outfit', sans-serif; transition: 0.4s;
color: var(--text-main);
overflow-x: hidden;
} }
.sidebar { .sidebar {
background: rgba(30, 41, 59, 0.9); background: var(--card); border-right: 1px solid rgba(255,255,255,0.1);
backdrop-filter: blur(15px); min-height: 100vh; padding: 2rem;
border-right: 1px solid rgba(255,255,255,0.1);
min-height: 100vh;
padding: 30px 20px;
} }
.glass-card { .glass-input {
background: var(--card-bg); background: rgba(0,0,0,0.2) !important; border: 1px solid rgba(255,255,255,0.1) !important;
border-radius: 20px; color: var(--text) !important; border-radius: 12px; padding: 10px;
border: 1px solid rgba(255,255,255,0.1);
padding: 25px;
margin-bottom: 25px;
} }
/* Chat Window îmbunătățit */ .kcal-hub {
.chat-container { background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
height: 65vh; border-radius: 20px; padding: 2rem; text-align: center; box-shadow: 0 10px 25px rgba(37, 99, 235, 0.3);
overflow-y: auto;
padding: 25px;
background: #020617;
border-radius: 20px;
margin-bottom: 20px;
border: 1px solid #1e293b;
} }
/* Bule Chat mai mari și mai lizibile */ .chat-area { height: 60vh; overflow-y: auto; padding: 20px; border-radius: 20px; background: rgba(0,0,0,0.1); }
.ai-msg {
background: #1e293b; .msg { padding: 1.5rem; border-radius: 1.5rem; margin-bottom: 1.5rem; max-width: 85%; font-size: 1.1rem; line-height: 1.6; }
color: #f1f5f9; .ai { background: var(--card); border-left: 5px solid #3b82f6; }
padding: 25px; .user { background: #10b981; margin-left: auto; color: white; font-weight: 500; }
border-radius: 20px 20px 20px 5px;
margin-bottom: 25px; .theme-selector { position: fixed; top: 20px; right: 20px; z-index: 1000; }
border-left: 6px solid var(--accent-blue); .input-bar {
font-size: 1.15rem; /* Text mai mare */ background: var(--card); border-radius: 50px; padding: 10px 25px;
line-height: 1.7; box-shadow: 0 4px 20px rgba(0,0,0,0.2); border: 1px solid rgba(255,255,255,0.1);
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
} }
.user-msg {
background: var(--accent-green);
color: white;
padding: 15px 25px;
border-radius: 20px 20px 5px 20px;
margin-bottom: 25px;
margin-left: 20%;
font-weight: 600;
font-size: 1.1rem;
box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}
.kcal-badge-ultra {
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
padding: 30px;
border-radius: 25px;
text-align: center;
box-shadow: 0 0 25px rgba(16, 185, 129, 0.5);
}
.form-control, .form-select {
background: #334155 !important;
border: 1px solid #475569 !important;
color: white !important;
padding: 14px;
font-size: 1rem;
}
.input-group-custom {
background: #1e293b;
border-radius: 50px;
padding: 8px 15px;
border: 2px solid #334155;
transition: 0.3s;
}
.input-group-custom:focus-within {
border-color: var(--accent-blue);
box-shadow: 0 0 15px rgba(59, 130, 246, 0.3);
}
#userInput {
background: transparent !important;
border: none !important;
font-size: 1.2rem;
color: white !important;
}
#userInput::placeholder { color: #64748b; }
.btn-send {
background: var(--accent-blue);
border-radius: 50%;
width: 55px;
height: 55px;
display: flex;
align-items: center;
justify-content: center;
border: none;
color: white;
transition: 0.3s;
}
.btn-send:hover { transform: scale(1.1); background: #2563eb; }
pre { font-size: 1.1rem; color: #e2e8f0; font-family: 'Poppins', sans-serif; white-space: pre-wrap; }
</style> </style>
</head> </head>
<body> <body>
<div class="theme-selector dropdown">
<button class="btn btn-dark rounded-pill px-4 shadow dropdown-toggle" data-bs-toggle="dropdown">
<i class="fas fa-palette me-2"></i>Aspect
</button>
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="#" onclick="setTheme('dark')">Dark Mode</a></li>
<li><a class="dropdown-item" href="#" onclick="setTheme('light')">Light Mode</a></li>
<li><a class="dropdown-item" href="#" onclick="setTheme('blue')">Ocean Blue</a></li>
</ul>
</div>
<div class="container-fluid"> <div class="container-fluid">
<div class="row"> <div class="row">
<div class="col-lg-3 sidebar shadow-lg"> <div class="col-lg-3 sidebar">
<h2 class="fw-bold mb-5 text-center"><i class="fas fa-heartbeat text-primary me-2"></i>Nutri<span class="text-primary">AI</span></h2> <h3 class="fw-bold mb-4"><i class="fas fa-dna me-2 text-primary"></i>Profil Bio</h3>
<div class="glass-card"> <div class="row g-3 mb-4">
<h6 class="text-uppercase small fw-bold text-primary mb-3"><i class="fas fa-user-circle me-2"></i>Date Biometrice</h6>
<div class="row g-3">
<div class="col-6"> <div class="col-6">
<label class="small text-muted mb-1">Greutate (kg)</label> <label class="small opacity-75">Vârstă</label>
<input type="number" id="greutate" class="form-control" value="85"> <input type="number" id="varsta" class="form-control glass-input" value="30">
</div> </div>
<div class="col-6"> <div class="col-6">
<label class="small text-muted mb-1">Înălțime (cm)</label> <label class="small opacity-75">Sex</label>
<input type="number" id="inaltime" class="form-control" value="180"> <select id="sex" class="form-select glass-input">
<option value="masculin">Masculin</option>
<option value="feminin">Feminin</option>
</select>
</div>
<div class="col-6">
<label class="small opacity-75">Înălțime (cm)</label>
<input type="number" id="inaltime" class="form-control glass-input" value="180">
</div>
<div class="col-6">
<label class="small opacity-75">Greutate (kg)</label>
<input type="number" id="greutate" class="form-control glass-input" value="85">
</div> </div>
<div class="col-12"> <div class="col-12">
<label class="small text-muted mb-1">Nivel Activitate</label> <label class="small opacity-75">Nivel Activitate</label>
<select id="activitate" class="form-select"> <select id="activitate" class="form-select glass-input">
<option value="1.2">Sedentar</option> <option value="1.2">Sedentar (Birou)</option>
<option value="1.55">Moderat</option> <option value="1.375">Ușor Activ (1-2 zile sport)</option>
<option value="1.75">Sportiv</option> <option value="1.55">Moderat Activ (3-5 zile sport)</option>
<option value="1.725">Foarte Activ (Zilnic/Fizic)</option>
</select> </select>
</div> </div>
</div> </div>
<div class="mb-4">
<label class="fw-bold d-flex justify-content-between">
Obiectiv <span><span id="objLabel">0</span> kcal</span>
</label>
<input type="range" class="form-range" id="kcalAdjust" min="-1000" max="1000" step="50" value="0">
</div> </div>
<div class="glass-card"> <div class="kcal-hub shadow-lg">
<h6 class="text-uppercase small fw-bold text-primary mb-3"><i class="fas fa-bullseye me-2"></i>Ajustare Obiectiv</h6> <small class="text-uppercase opacity-75">Ținta ta calorică</small>
<input type="range" class="form-range" id="kcalAdjust" min="-800" max="800" step="50" value="0"> <h1 class="fw-bold display-5 mb-0" id="totalKcal">2500</h1>
<div class="d-flex justify-content-between mt-2 fw-bold text-info"> <span class="small fw-bold">KCAL / ZI</span>
<span>Slăbire</span>
<span id="sliderLabel">0 kcal</span>
<span>Masă</span>
</div>
</div> </div>
<div class="kcal-badge-ultra"> <button onclick="updateProfile()" class="btn btn-primary w-100 mt-4 py-3 fw-bold rounded-pill">
<span class="text-uppercase small fw-bold opacity-75">Necesar Zilnic</span> <i class="fas fa-sync-alt me-2"></i>ACTUALIZEAZĂ DATE
<h1 class="fw-bold mb-0" id="totalKcal">2500</h1>
<span class="fw-bold">KCAL / ZI</span>
</div>
<button onclick="calculateAndSync()" class="btn btn-primary w-100 mt-4 py-3 fw-bold rounded-pill shadow">
<i class="fas fa-sync-alt me-2"></i>RECALCULEAZĂ
</button> </button>
</div> </div>
<div class="col-lg-9 p-md-5 p-3"> <div class="col-lg-9 p-5">
<div class="d-flex align-items-center mb-4"> <h2 class="fw-bold mb-4">Asistent Personalizat AI</h2>
<div class="flex-grow-1"> <div id="chatBox" class="chat-area shadow-inner">
<h1 class="fw-bold mb-1">Asistent Nutriție Elite</h1> <div class="msg ai shadow-sm">
<p class="text-muted"><i class="fas fa-bolt text-warning me-2"></i>Procesare ultra-rapidă prin Groq Llama 3.3</p> <h5 class="fw-bold">Sistem Gata.</h5>
Salut! Sunt antrenorul tău digital. Am preluat toate detaliile tale biometrice. <br>
<strong>Cu ce începem?</strong> Îmi poți cere un meniu saptamanal sau un plan de antrenament.
</div> </div>
</div> </div>
<div id="chatBox" class="chat-container shadow-2xl"> <div class="input-bar d-flex align-items-center mt-4">
<div class="ai-msg"> <input type="text" id="userInput" class="form-control bg-transparent border-0 text-white"
<h4 class="fw-bold mb-3"><i class="fas fa-robot me-2"></i>Sistemul este pregătit.</h4> placeholder="Scrie aici și apasă ENTER..." style="font-size: 1.2rem;">
Salut! Am configurat profilul tău pentru <strong id="kcalTag">2500</strong> calorii. <br> <button onclick="sendToGroq()" class="btn btn-primary rounded-circle p-3 ms-2" style="width: 55px; height: 55px;">
<strong>Ce dorești să facem?</strong> Poți cere un meniu pe o zi, pe o săptămână sau chiar o rețetă specifică.
</div>
</div>
<div class="input-group-custom d-flex align-items-center mt-4 shadow-lg">
<input type="text" id="userInput" class="form-control" placeholder="Scrie aici mesajul tău și apasă ENTER...">
<button onclick="sendToGroq()" class="btn btn-send shadow">
<i class="fas fa-paper-plane"></i> <i class="fas fa-paper-plane"></i>
</button> </button>
</div> </div>
@@ -208,80 +137,61 @@
</div> </div>
</div> </div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script> <script>
const GROQ_API_KEY = "AICI_PUI_CHEIA_TA_GROQ"; const GROQ_API_KEY = "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";
let currentKcal = 0; let currentKcal = 0;
// --- FUNCȚIA ENTER KEY --- function setTheme(theme) {
document.getElementById('userInput').addEventListener('keypress', function (e) { document.body.className = theme + '-theme';
if (e.key === 'Enter') {
sendToGroq();
} }
});
document.getElementById('kcalAdjust').addEventListener('input', function() { document.getElementById('userInput').addEventListener('keypress', (e) => { if(e.key === 'Enter') sendToGroq(); });
document.getElementById('sliderLabel').innerText = (this.value > 0 ? '+' : '') + this.value + " kcal";
calculateAndSync();
});
function calculateAndSync() { function updateProfile() {
const g = parseFloat(document.getElementById('greutate').value); const v = parseFloat(document.getElementById('varsta').value);
const s = document.getElementById('sex').value;
const i = parseFloat(document.getElementById('inaltime').value); const i = parseFloat(document.getElementById('inaltime').value);
const g = parseFloat(document.getElementById('greutate').value);
const act = parseFloat(document.getElementById('activitate').value); const act = parseFloat(document.getElementById('activitate').value);
const adj = parseInt(document.getElementById('kcalAdjust').value); const adj = parseInt(document.getElementById('kcalAdjust').value);
let bmr = (10 * g) + (6.25 * i) - (5 * 30) + 5; let bmr = (s === 'masculin') ? (10 * g) + (6.25 * i) - (5 * v) + 5 : (10 * g) + (6.25 * i) - (5 * v) - 161;
currentKcal = Math.round((bmr * act) + adj); currentKcal = Math.round((bmr * act) + adj);
document.getElementById('totalKcal').innerText = currentKcal; document.getElementById('totalKcal').innerText = currentKcal;
document.getElementById('kcalTag').innerText = currentKcal; document.getElementById('objLabel').innerText = (adj > 0 ? '+' : '') + adj;
} }
async function sendToGroq() { async function sendToGroq() {
const input = document.getElementById('userInput'); const input = document.getElementById('userInput');
const userText = input.value.trim(); const text = input.value.trim();
if(!userText) return; if(!text) return;
addMessage("user", userText); addMsg('user', text);
input.value = ""; input.value = "";
const loadId = 'load-' + Date.now();
const loadingId = "loading-" + Date.now(); addMsg('ai', '<div class="spinner-border spinner-border-sm text-primary"></div> Gândesc...', loadId);
addMessage("ai", '<div class="spinner-border spinner-border-sm text-info me-2"></div> Se generează răspunsul...', loadingId);
try { try {
const response = await fetch("https://api.groq.com/openai/v1/chat/completions", { const resp = await fetch("https://api.groq.com/openai/v1/chat/completions", {
method: "POST", method: "POST", headers: { "Authorization": `Bearer ${GROQ_API_KEY}`, "Content-Type": "application/json" },
headers: {
"Authorization": `Bearer ${GROQ_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ body: JSON.stringify({
model: "llama-3.3-70b-versatile", model: "llama-3.3-70b-versatile",
messages: [ messages: [{ role: "system", content: `Ești un nutriționist expert. Profil utilizator: ${currentKcal} kcal/zi. Răspunde în ROMÂNĂ cu meniuri și sfaturi saptamanale.` }, { role: "user", content: text }]
{
role: "system",
content: `Ești un nutriționist de top. Ținta utilizatorului este de ${currentKcal} kcal. Răspunde exclusiv în ROMÂNĂ. Folosește Markdown (tabele, liste) pentru claritate maximă.`
},
{ role: "user", content: userText }
]
}) })
}); });
const data = await resp.json();
const data = await response.json(); document.getElementById(loadId).innerHTML = `<div style="white-space: pre-wrap">${data.choices[0].message.content}</div>`;
const text = data.choices[0].message.content; } catch(e) { document.getElementById(loadId).innerText = "Eroare de conexiune!"; }
document.getElementById(loadingId).innerHTML = `<pre>${text}</pre>`;
} catch (error) {
document.getElementById(loadingId).innerText = "Eroare la conexiunea cu AI-ul!";
}
} }
function addMessage(type, msg, id = null) { function addMsg(type, content, id = null) {
const box = document.getElementById('chatBox'); const b = document.getElementById('chatBox');
box.innerHTML += `<div class="${type}-msg" ${id ? `id="${id}"` : ''}>${msg}</div>`; b.innerHTML += `<div class="msg ${type} shadow-sm" ${id ? `id="${id}"` : ''}>${content}</div>`;
box.scrollTop = box.scrollHeight; b.scrollTop = b.scrollHeight;
} }
updateProfile();
calculateAndSync();
</script> </script>
</body> </body>
</html> </html>