// ========== ДАННЫЕ О ЛЕКАРСТВАХ ========== const MEDICATIONS = [ // УТРО (7:00) { name: "Эутирокс", dose: "1 таблетка", time: "07:00", period: "утро", instruction: "утром" }, { name: "Йодомарин", dose: "1 таблетка", time: "07:00", period: "утро", instruction: "после завтрака" }, { name: "Биовит", dose: "1 ст. ложка", time: "07:00", period: "утро", instruction: "после еды" }, // ПЕРЕД ОБЕДОМ (11:30) { name: "Одестон 200", dose: "1 таблетка", time: "11:30", period: "обед", instruction: "за 20 мин до еды" }, { name: "Аминосорб", dose: "1 ст. ложка", time: "11:30", period: "обед", instruction: "за 30 мин до еды" }, // ОБЕД (12:00) { name: "Креон", dose: "3 таблетки", time: "12:00", period: "обед", instruction: "во время еды" }, // ПОСЛЕ ОБЕДА (14:00) { name: "Урсосан 250", dose: "2 таблетки", time: "14:00", period: "обед", instruction: "после обеда" }, { name: "Биовит", dose: "1 ст. ложка", time: "14:00", period: "обед", instruction: "после еды" }, // ПЕРЕД УЖИНОМ (17:30) { name: "Одестон 200", dose: "1 таблетка", time: "17:30", period: "ужин", instruction: "за 20 мин до еды" }, { name: "Аминосорб", dose: "1 ст. ложка", time: "17:30", period: "ужин", instruction: "за 30 мин до еды" }, // УЖИН (18:00) { name: "Креон", dose: "3 таблетки", time: "18:00", period: "ужин", instruction: "во время еды" }, // ПОСЛЕ УЖИНА (20:00) { name: "Урсосан 250", dose: "2 таблетки", time: "20:00", period: "ужин", instruction: "после ужина" }, { name: "Биовит", dose: "1 ст. ложка", time: "20:00", period: "ужин", instruction: "после еды" } ]; // Уникальные времена const TIMES = ["07:00", "11:30", "12:00", "14:00", "17:30", "18:00", "20:00"]; // ========== СОСТОЯНИЕ ========== let takenMeds = JSON.parse(localStorage.getItem('meds_taken') || '{}'); let notificationPermission = 'default'; let audioCtx = null; // ========== ИНИЦИАЛИЗАЦИЯ ========== document.addEventListener('DOMContentLoaded', () => { checkNotificationPermission(); renderSchedule(); updateClock(); setInterval(updateClock, 1000); setInterval(checkReminders, 10000); updateTakenCount(); }); // ========== ЧАСЫ ========== function updateClock() { const now = new Date(); document.getElementById('current-time').textContent = now.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit', second: '2-digit' }); updateNextReminder(); updateStatus(); } // ========== УВЕДОМЛЕНИЯ ========== function checkNotificationPermission() { if (!('Notification' in window)) { document.getElementById('notif-status').textContent = 'Браузер не поддерживает уведомления'; document.getElementById('notif-btn').classList.add('hidden'); return; } notificationPermission = Notification.permission; updateNotificationUI(); } function updateNotificationUI() { const status = document.getElementById('notif-status'); const btn = document.getElementById('notif-btn'); if (notificationPermission === 'granted') { status.textContent = '✅ Уведомления включены'; btn.classList.add('hidden'); } else if (notificationPermission === 'denied') { status.textContent = '❌ Уведомления заблокированы. Включите в настройках браузера'; btn.classList.add('hidden'); } else { status.textContent = 'Уведомления не включены'; btn.classList.remove('hidden'); } } function requestNotificationPermission() { if (!('Notification' in window)) return; Notification.requestPermission().then(permission => { notificationPermission = permission; updateNotificationUI(); if (permission === 'granted') { sendNotification('Готово! 🔔', 'Уведомления о приёме лекарств включены'); } }); } function sendNotification(title, body) { if (notificationPermission === 'granted') { new Notification(title, { body: body, icon: '💊', badge: '💊', tag: 'med-reminder', requireInteraction: true }); } playSound(); } // ========== ЗВУК ========== function playSound() { try { if (!audioCtx) { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); } const oscillator = audioCtx.createOscillator(); const gainNode = audioCtx.createGain(); oscillator.connect(gainNode); gainNode.connect(audioCtx.destination); oscillator.frequency.value = 800; oscillator.type = 'sine'; gainNode.gain.setValueAtTime(0.3, audioCtx.currentTime); gainNode.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + 0.5); oscillator.start(audioCtx.currentTime); oscillator.stop(audioCtx.currentTime + 0.5); } catch (e) { console.log('Audio not supported'); } } // ========== РАСПИСАНИЕ ========== function renderSchedule() { const container = document.getElementById('schedule'); const now = new Date(); const currentTime = now.getHours().toString().padStart(2, '0') + ':' + now.getMinutes().toString().padStart(2, '0'); let html = ''; for (const time of TIMES) { const medsAtTime = MEDICATIONS.filter(m => m.time === time); const isPast = time < currentTime; const isCurrent = isTimeNear(time, currentTime); let blockClass = 'time-block'; if (isCurrent) blockClass += ' active'; else if (isPast) blockClass += ' past'; html += `