proekttarym-kayda/script.js

253 lines
9.0 KiB
JavaScript

var EXERCISES = [
{ ico: "🌬️", name: "Тыныс алу жаттығуы", dur: 60, desc: "Диафрагмамен терең тыныста: ішті үрлеп жұт, баяу шығар" },
{ ico: "🙆", name: "Мойын қозғалыстары", dur: 60, desc: "Мойынды баяу алға-артқа, солға-оңға еңкейт (айналдырмай)" },
{ ico: "🤸", name: "Иық айналдыру", dur: 60, desc: "Иықты алға, содан артқа айналдыр — әр бағытта 10 рет" },
{ ico: "✊", name: "Қол буындарын қозғау", dur: 45, desc: "Жұдырық жұм, аш; саусақтарды веермен жаз" },
{ ico: "🐱", name: "«Мысық пен сиыр»", dur: 60, desc: "Төрт аяқтап тұрып, арқаны дөңгелектеп, содан иілдір" },
{ ico: "🦵", name: "Жамбас буындары", dur: 60, desc: "Шалқадан жатып, тізені кеудеге тарт, екінші аяқты түзу ұста" },
{ ico: "🦿", name: "Тізе қозғалыстары", dur: 60, desc: "Отырып немесе жатып, тізені баяу бүк-жаз" },
{ ico: "🦶", name: "Тобық айналдыру", dur: 45, desc: "Әр аяқтың тобығын сағат тілімен және қарсы айналдыр" }
];
var state = {
list: document.getElementById("exList"),
ring: document.getElementById("ring"),
time: document.getElementById("time"),
name: document.getElementById("timerName"),
startBtn: document.getElementById("startBtn"),
resetBtn: document.getElementById("resetBtn"),
skipBtn: document.getElementById("skipBtn"),
autoBtn: document.getElementById("autoBtn"),
progText: document.getElementById("progText"),
progBar: document.getElementById("progBar"),
index: 0,
running: false,
auto: false,
left: EXERCISES[0].dur,
total: 0,
int: null
};
function fmt(s) {
var m = Math.floor(s / 60), ss = s % 60;
return (m < 10 ? "0" : "") + m + ":" + (ss < 10 ? "0" : "") + ss;
}
function render() {
var html = EXERCISES.map(function (e, i) {
var cls = i === state.index ? " active" : "";
if (state.auto && i === state.index) cls = " on";
if (state.auto && i < state.index) cls = " done";
var st = i < state.index ? "✓" : (i === state.index && state.running ? "…" : fmt(e.dur));
return '<div class="ex' + cls + '" data-i="' + i + '">' +
'<div class="ex-ico">' + e.ico + '</div>' +
'<div class="ex-body"><div class="ex-name">' + e.name + '</div>' +
'<div class="ex-time">' + e.desc + '</div></div>' +
'<div class="ex-state">' + st + '</div></div>';
}).join("");
state.list.innerHTML = html;
state.list.querySelectorAll(".ex").forEach(function (el) {
el.addEventListener("click", function () { pick(parseInt(el.dataset.i, 10)); });
});
updateRing();
updateProg();
}
function updateRing() {
var done = state.total - state.left;
var pct = state.total > 0 ? (done / state.total) * 360 : 0;
state.ring.style.background = "conic-gradient(var(--cyan) " + pct + "deg, #223043 0deg)";
state.time.textContent = fmt(state.left);
state.name.textContent = EXERCISES[state.index].name;
}
function updateProg() {
if (!state.auto) {
state.progText.textContent = "Жеке жаттығу";
state.progBar.style.width = "0%";
return;
}
var done = state.index;
state.progText.textContent = (done + 1) + " / " + EXERCISES.length;
state.progBar.style.width = (done / EXERCISES.length * 100) + "%";
}
function beep() {
try {
var ctx = new (window.AudioContext || window.webkitAudioContext)();
var o = ctx.createOscillator(), g = ctx.createGain();
o.connect(g); g.connect(ctx.destination);
o.frequency.value = 660; g.gain.value = 0.18;
o.start();
setTimeout(function () { o.stop(); ctx.close(); }, 350);
} catch (e) {}
}
function stop() {
clearInterval(state.int);
state.int = null;
state.running = false;
state.startBtn.textContent = "▶ Бастау";
}
function tick() {
state.left--;
if (state.left <= 0) {
beep();
next();
return;
}
updateRing();
}
function start() {
if (state.running) { stop(); render(); return; }
state.running = true;
state.startBtn.textContent = "⏸ Тоқтау";
state.int = setInterval(tick, 1000);
render();
}
function next() {
clearInterval(state.int);
state.int = null;
if (state.auto) {
state.index++;
if (state.index >= EXERCISES.length) {
state.auto = false;
state.index = 0;
state.left = EXERCISES[0].dur;
state.total = EXERCISES[0].dur;
state.running = false;
state.autoBtn.textContent = "🎯 Толық кешенді бастау (барлық 8 жаттығу)";
state.startBtn.textContent = "▶ Бастау";
beep(); beep();
render();
return;
}
state.left = EXERCISES[state.index].dur;
state.total = state.left;
render();
state.running = true;
state.int = setInterval(tick, 1000);
return;
}
state.index = (state.index + 1) % EXERCISES.length;
state.left = EXERCISES[state.index].dur;
state.total = state.left;
state.running = false;
render();
}
function pick(i) {
stop();
state.auto = false;
state.autoBtn.textContent = "🎯 Толық кешенді бастау (барлық 8 жаттығу)";
state.index = i;
state.left = EXERCISES[i].dur;
state.total = state.left;
render();
}
function reset() {
stop();
state.left = EXERCISES[state.index].dur;
state.total = state.left;
render();
}
function startAuto() {
stop();
state.auto = true;
state.index = 0;
state.left = EXERCISES[0].dur;
state.total = state.left;
state.autoBtn.textContent = "⏸ Кешен жүріп жатыр…";
state.startBtn.textContent = "▶ Бастау";
render();
start();
}
state.startBtn.addEventListener("click", start);
state.resetBtn.addEventListener("click", reset);
state.skipBtn.addEventListener("click", function () { stop(); next(); });
state.autoBtn.addEventListener("click", startAuto);
render();
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (e) { if (e.isIntersecting) e.target.classList.add("in"); });
}, { threshold: .15 });
document.querySelectorAll(".reveal").forEach(function (el) { io.observe(el); });
var chatBox = document.getElementById("chatBox");
var chatInput = document.getElementById("chatInput");
var chatSend = document.getElementById("chatSend");
function addMsg(who, text) {
var d = document.createElement("div");
d.className = "msg " + who;
d.textContent = text;
chatBox.appendChild(d);
chatBox.scrollTop = chatBox.scrollHeight;
}
function addQuickLinks(text) {
var t = text.toLowerCase();
var links = [];
if (t.indexOf("жаттығу") !== -1 || t.indexOf("жаттыгу") !== -1 || t.indexOf("қозғал") !== -1 || t.indexOf("козгал") !== -1) {
links.push({ href: "#timer", label: "▶ Жаттығу бөлімі" });
}
if (t.indexOf("мазь") !== -1 || t.indexOf("укол") !== -1 || t.indexOf("дәрі") !== -1 || t.indexOf("дәр") !== -1 || t.indexOf("дори") !== -1 || t.indexOf("гель") !== -1) {
links.push({ href: "#drugs", label: "💊 Дәрілер бөлімі" });
links.push({ href: "#pharm", label: "🛒 Онлайн-аптека" });
}
if (!links.length) return;
var row = document.createElement("div");
row.className = "msg-quick";
links.forEach(function (l) {
var a = document.createElement("a");
a.className = "btn btn-ghost btn-quick";
a.href = l.href;
a.textContent = l.label;
a.addEventListener("click", function () {
var sec = document.querySelector(l.href);
if (sec) sec.scrollIntoView({ behavior: "smooth" });
});
row.appendChild(a);
});
chatBox.appendChild(row);
chatBox.scrollTop = chatBox.scrollHeight;
}
async function sendChat() {
var text = chatInput.value.trim();
if (!text) return;
addMsg("user", text);
chatInput.value = "";
var waiting = document.createElement("div");
waiting.className = "msg bot typing";
waiting.textContent = "Жазып жатыр…";
chatBox.appendChild(waiting);
chatBox.scrollTop = chatBox.scrollHeight;
try {
var r = await fetch("/api/advice", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text: text })
});
var j = await r.json();
waiting.remove();
if (j.ok) { addMsg("bot", j.answer); addQuickLinks(j.answer); }
else addMsg("bot", "Кешіріңіз, жауап қазір келмеді. Кейінірек қайталап көріңіз немесе шағымыңды басқаша жазып жіберіңіз.");
} catch (e) {
waiting.remove();
addMsg("bot", "Қате болды. Байланысты тексеріп, қайталап көріңіз.");
}
}
chatSend.addEventListener("click", sendChat);
chatInput.addEventListener("keydown", function (e) {
if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); sendChat(); }
});