Replace browser notifications with manual WhatsApp reminders
Drop Notification API (only fires when tab open). Instead render two wa.me deep-link buttons that pre-fill reminder text to the user's own WhatsApp number (77477854246). Steps button auto-picks 5k (weekday) or 10k (weekend) based on current day. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
24136595b7
commit
9de414fefe
111
index.html
111
index.html
@ -121,6 +121,18 @@
|
||||
font-weight: 500;
|
||||
font-size: 0.88rem;
|
||||
}
|
||||
.wa-btn {
|
||||
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
||||
background: linear-gradient(135deg, #25d366, #128c7e);
|
||||
color: white; text-decoration: none;
|
||||
padding: 12px 18px;
|
||||
border-radius: 12px;
|
||||
font-weight: 600; font-size: 0.95rem;
|
||||
box-shadow: 0 4px 14px rgba(37, 211, 102, 0.3);
|
||||
transition: transform .15s ease, box-shadow .2s ease;
|
||||
}
|
||||
.wa-btn:hover { transform: translateY(-1px); box-shadow: 0 6px 20px rgba(37, 211, 102, 0.45); }
|
||||
.wa-btn:active { transform: translateY(0); }
|
||||
button.link:hover {
|
||||
background: var(--accent-soft);
|
||||
transform: none;
|
||||
@ -338,11 +350,12 @@
|
||||
</section>
|
||||
|
||||
<section id="reminders">
|
||||
<h2>🔔 Напоминания</h2>
|
||||
<p>Шаги (будни 5 000, выходные 10 000) — в 12:00.<br/>Instagram — раз в неделю, воскресенье 11:00.</p>
|
||||
<button id="enable-notifications">Включить уведомления</button>
|
||||
<span id="notif-status" class="muted"></span>
|
||||
<p class="muted small">⚠️ Уведомления приходят только пока вкладка открыта. Для пуша когда сайт закрыт нужен Service Worker — это следующий шаг.</p>
|
||||
<h2>🔔 Напоминания в WhatsApp</h2>
|
||||
<p class="muted small">Жми кнопку — откроется WhatsApp с готовым текстом, отправь себе.</p>
|
||||
<div style="display:flex; flex-direction:column; gap:10px; margin-top:12px;">
|
||||
<a id="wa-steps" class="wa-btn" target="_blank" rel="noopener">👟 <span id="wa-steps-label">Шаги сегодня</span></a>
|
||||
<a id="wa-ig" class="wa-btn" target="_blank" rel="noopener">📷 Опубликовать историю в Instagram</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="checklist">
|
||||
@ -464,11 +477,13 @@
|
||||
];
|
||||
|
||||
const REMINDERS = {
|
||||
weekdaySteps: { time: "12:00", text: "Пройти 5 000 шагов сегодня" },
|
||||
weekendSteps: { time: "12:00", text: "Пройти 10 000 шагов сегодня" },
|
||||
instagram: { day: 0, time: "11:00", text: "Опубликовать одну историю в Instagram (@zhanara2964)" }
|
||||
weekdaySteps: { text: "Пройти 5 000 шагов сегодня 👟" },
|
||||
weekendSteps: { text: "Пройти 10 000 шагов сегодня 👟" },
|
||||
instagram: { text: "Опубликовать одну историю в Instagram (@zhanara2964) 📷" }
|
||||
};
|
||||
|
||||
const WHATSAPP_NUMBER = "77477854246";
|
||||
|
||||
const PASSWORD = "zhanar2026";
|
||||
|
||||
/* ===== AUTH ===== */
|
||||
@ -615,77 +630,27 @@
|
||||
});
|
||||
})();
|
||||
|
||||
/* ===== REMINDERS ===== */
|
||||
/* ===== REMINDERS (WhatsApp manual) ===== */
|
||||
(function () {
|
||||
const btn = document.getElementById("enable-notifications");
|
||||
const status = document.getElementById("notif-status");
|
||||
const FIRED_KEY = "reminders-fired";
|
||||
const stepsBtn = document.getElementById("wa-steps");
|
||||
const stepsLabel = document.getElementById("wa-steps-label");
|
||||
const igBtn = document.getElementById("wa-ig");
|
||||
|
||||
function todayKey() { return new Date().toISOString().slice(0, 10); }
|
||||
function waLink(text) {
|
||||
return "https://wa.me/" + WHATSAPP_NUMBER + "?text=" + encodeURIComponent(text);
|
||||
}
|
||||
|
||||
function firedToday(tag) {
|
||||
try {
|
||||
const data = JSON.parse(localStorage.getItem(FIRED_KEY) || "{}");
|
||||
return data[todayKey()] && data[todayKey()][tag];
|
||||
} catch (e) { return false; }
|
||||
}
|
||||
function markFired(tag) {
|
||||
let data;
|
||||
try { data = JSON.parse(localStorage.getItem(FIRED_KEY) || "{}"); }
|
||||
catch (e) { data = {}; }
|
||||
const k = todayKey();
|
||||
Object.keys(data).forEach(function (d) { if (d !== k) delete data[d]; });
|
||||
data[k] = data[k] || {};
|
||||
data[k][tag] = true;
|
||||
localStorage.setItem(FIRED_KEY, JSON.stringify(data));
|
||||
}
|
||||
function updateStatus() {
|
||||
if (!("Notification" in window)) {
|
||||
status.textContent = "не поддерживается в этом браузере";
|
||||
btn.disabled = true;
|
||||
return;
|
||||
}
|
||||
const p = Notification.permission;
|
||||
if (p === "granted") {
|
||||
status.textContent = "✅ включены";
|
||||
btn.textContent = "Уведомления включены";
|
||||
btn.disabled = true;
|
||||
} else if (p === "denied") {
|
||||
status.textContent = "❌ заблокированы в браузере";
|
||||
btn.disabled = true;
|
||||
} else {
|
||||
status.textContent = "не запрошены";
|
||||
}
|
||||
}
|
||||
function checkAndFire() {
|
||||
if (Notification.permission !== "granted") return;
|
||||
const now = new Date();
|
||||
const hhmm = now.toTimeString().slice(0, 5);
|
||||
const dow = now.getDay();
|
||||
function refresh() {
|
||||
const dow = new Date().getDay();
|
||||
const isWeekend = dow === 0 || dow === 6;
|
||||
|
||||
const steps = isWeekend ? REMINDERS.weekendSteps : REMINDERS.weekdaySteps;
|
||||
if (hhmm === steps.time && !firedToday("steps")) {
|
||||
new Notification("Шаги", { body: steps.text });
|
||||
markFired("steps");
|
||||
}
|
||||
const ig = REMINDERS.instagram;
|
||||
if (dow === ig.day && hhmm === ig.time && !firedToday("ig")) {
|
||||
new Notification("Instagram", { body: ig.text });
|
||||
markFired("ig");
|
||||
}
|
||||
stepsBtn.href = waLink(steps.text);
|
||||
stepsLabel.textContent = steps.text;
|
||||
igBtn.href = waLink(REMINDERS.instagram.text);
|
||||
}
|
||||
btn.addEventListener("click", function () {
|
||||
if (!("Notification" in window)) return;
|
||||
Notification.requestPermission().then(function (p) {
|
||||
updateStatus();
|
||||
if (p === "granted") {
|
||||
new Notification("Уведомления включены", { body: "Я буду напоминать о шагах и Instagram." });
|
||||
}
|
||||
});
|
||||
});
|
||||
updateStatus();
|
||||
setInterval(checkAndFire, 60_000);
|
||||
|
||||
refresh();
|
||||
setInterval(refresh, 60 * 60 * 1000);
|
||||
})();
|
||||
|
||||
/* ===== APP (render) ===== */
|
||||
|
||||
Reference in New Issue
Block a user