Files
takeyourmeds/public/lib/ui.js
T
2026-06-10 09:43:50 +02:00

88 lines
3.3 KiB
JavaScript

const STATUS_LABELS = {
upcoming: "Noch nicht",
pending: "Jetzt!",
overdue: "Überfällig",
snoozed: "Snoozed",
taken: "Genommen ✓",
missed: "Verpasst",
};
export function showToast(msg, ms = 3000) {
const el = document.getElementById("toast");
el.textContent = msg;
el.hidden = false;
clearTimeout(el._timer);
el._timer = setTimeout(() => { el.hidden = true; }, ms);
}
export function showConfetti() {
const el = document.getElementById("confetti");
el.hidden = false;
el.classList.add("show");
setTimeout(() => { el.hidden = true; el.classList.remove("show"); }, 650);
}
export function showEasterEgg(title, text) {
const overlay = document.getElementById("easterEgg");
overlay.innerHTML = `
<div class="easterEggInner">
<h2>🏆 ${title}</h2>
<p>${text}</p>
<button type="button" class="btn btn-primary" id="easterClose">Nice</button>
</div>`;
overlay.hidden = false;
overlay.querySelector("#easterClose").addEventListener("click", () => {
overlay.hidden = true;
overlay.innerHTML = "";
});
}
export function renderSlots(slots, onTake, onSnooze) {
const container = document.getElementById("slotCards");
container.innerHTML = slots.map((slot) => {
const taken = slot.status === "taken";
const canTake = ["pending", "overdue", "snoozed", "upcoming"].includes(slot.status);
return `
<div class="slotCard status-${slot.status}" data-slot="${slot.id}">
<div class="slotHeader">
<span class="slotLabel">${slot.label}</span>
<span class="slotTime">${slot.time}</span>
</div>
<div class="slotMeds">${slot.meds.map((m) => `${m.name} ${m.dose}`).join(", ")}</div>
<span class="slotStatus">${STATUS_LABELS[slot.status] || slot.status}</span>
${canTake && !taken ? `
<div class="slotActions">
<button type="button" class="btn btn-primary" data-action="take" data-slot="${slot.id}">Genommen ✓</button>
<button type="button" class="btn btn-snooze" data-action="snooze15" data-slot="${slot.id}">+15 Min</button>
<button type="button" class="btn btn-snooze" data-action="snooze30" data-slot="${slot.id}">+30 Min</button>
</div>` : ""}
</div>`;
}).join("");
container.querySelectorAll("[data-action]").forEach((btn) => {
btn.addEventListener("click", () => {
const slotId = btn.dataset.slot;
const action = btn.dataset.action;
if (action === "take") onTake(slotId);
else if (action === "snooze15") onSnooze(slotId, 15);
else if (action === "snooze30") onSnooze(slotId, 30);
});
});
}
export function renderHeatmap(days) {
const container = document.getElementById("heatmap");
container.innerHTML = days.map((d) =>
`<div class="heatCell ${d.level}" title="${d.day}"></div>`
).join("");
}
export function updateStats(stats) {
document.getElementById("statStreak").textContent = stats.streak;
document.getElementById("statCompliance").textContent = `${stats.compliance_percent}%`;
const windowDays = stats.compliance_window_days ?? 90;
document.getElementById("statComplianceLabel").textContent = windowDays === 1 ? "1 Tag" : `${windowDays} Tage`;
document.getElementById("statTaken").textContent = stats.total_taken;
document.getElementById("streakBadge").textContent = `🔥 ${stats.streak}`;
}