document.addEventListener('DOMContentLoaded', function () { const alarmForm = document.getElementById('createAlarmForm'); const alarmsList = document.getElementById('alarmList'); const alarmModal = new bootstrap.Modal(document.getElementById('alarmModal')); const alarmSound = document.getElementById('alarmSound'); const dismissAlarmBtn = document.getElementById('dismissAlarmBtn'); const enableNotificationsBtn = document.getElementById('enable-notifications'); const notificationPermissionCard = document.getElementById('notification-permission-card'); // --- Notification Permission Handling --- function handleNotificationPermission(permission) { if (permission === 'granted') { if (notificationPermissionCard) { notificationPermissionCard.style.display = 'none'; } } else if (permission === 'denied') { if (notificationPermissionCard) { notificationPermissionCard.innerHTML = '
You have blocked notifications. To use alarms, you need to enable them in your browser settings.
'; } } else { if (notificationPermissionCard) { notificationPermissionCard.style.display = 'block'; } } } // Check initial notification permission status if ('Notification' in window) { handleNotificationPermission(Notification.permission); } else { // Notifications not supported if (notificationPermissionCard) { notificationPermissionCard.innerHTML = '
This browser does not support desktop notifications.
'; } } // Request notification permission on button click if (enableNotificationsBtn) { enableNotificationsBtn.addEventListener('click', () => { Notification.requestPermission().then(permission => { handleNotificationPermission(permission); }); }); } // --- Alarm Logic --- // Function to fetch and display alarms const fetchAlarms = () => { fetch('/api/alarms.php?action=get') .then(response => response.json()) .then(data => { if (data.success && data.alarms) { // Clear only if there are alarms to show if(data.alarms.length > 0) { alarmsList.innerHTML = ''; } document.getElementById('noAlarmsMessage')?.remove(); data.alarms.forEach(alarm => { addAlarmToList(alarm); }); } }); }; // Function to add a single alarm to the list const addAlarmToList = (alarm) => { const { id, alarm_time, label, is_active, note_id } = alarm; const listItem = document.createElement('li'); listItem.className = 'list-group-item d-flex justify-content-between align-items-center'; listItem.dataset.id = id; const alarmDisplay = document.createElement('div'); alarmDisplay.className = 'd-flex align-items-center'; const switchDiv = document.createElement('div'); switchDiv.className = 'form-check form-switch me-3'; const switchInput = document.createElement('input'); switchInput.className = 'form-check-input toggle-alarm-switch'; switchInput.type = 'checkbox'; switchInput.role = 'switch'; switchInput.id = `toggle-${id}`; switchInput.checked = !!parseInt(is_active); switchInput.addEventListener('change', () => handleToggleAlarm(id, switchInput.checked)); const switchLabel = document.createElement('label'); switchLabel.className = 'form-check-label'; switchLabel.setAttribute('for', `toggle-${id}`); switchDiv.appendChild(switchInput); switchDiv.appendChild(switchLabel); const timeDiv = document.createElement('div'); const timeSpan = document.createElement('span'); timeSpan.className = 'fw-bold fs-5'; timeSpan.textContent = new Date(`1970-01-01T${alarm_time}`).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', hour12: true }); const labelSpan = document.createElement('span'); labelSpan.className = 'text-muted ms-2'; labelSpan.textContent = label; timeDiv.appendChild(timeSpan); timeDiv.appendChild(labelSpan); alarmDisplay.appendChild(switchDiv); alarmDisplay.appendChild(timeDiv); const deleteForm = document.createElement('form'); deleteForm.className = 'delete-alarm-form'; deleteForm.addEventListener('submit', (e) => { e.preventDefault(); handleDeleteAlarm(id); }); const hiddenAction = document.createElement('input'); hiddenAction.type = 'hidden'; hiddenAction.name = 'action'; hiddenAction.value = 'delete'; const hiddenId = document.createElement('input'); hiddenId.type = 'hidden'; hiddenId.name = 'alarm_id'; hiddenId.value = id; const deleteButton = document.createElement('button'); deleteButton.type = 'submit'; deleteButton.className = 'btn btn-sm btn-outline-danger'; deleteButton.innerHTML = ''; deleteForm.appendChild(hiddenAction); deleteForm.appendChild(hiddenId); deleteForm.appendChild(deleteButton); listItem.appendChild(alarmDisplay); listItem.appendChild(deleteForm); // Remove "no alarms" message if it exists const noAlarmsMsg = document.getElementById('noAlarmsMessage'); if (noAlarmsMsg) { noAlarmsMsg.remove(); } alarmsList.appendChild(listItem); feather.replace(); }; // Handle form submission to create a new alarm if (alarmForm) { alarmForm.addEventListener('submit', function (e) { e.preventDefault(); const time = document.getElementById('alarmTime').value; const label = document.getElementById('alarmLabel').value; if (!time) { alert('Please select a time for the alarm.'); return; } const formData = new FormData(); formData.append('alarm_time', time); formData.append('label', label); fetch('/api/alarms.php?action=create', { method: 'POST', body: formData }) .then(response => response.json()) .then(data => { if (data.success) { addAlarmToList(data.alarm); alarmForm.reset(); } else { alert('Error: ' + (data.error || 'Could not create alarm.')); } }); }); } // Handle deleting an alarm const handleDeleteAlarm = (id) => { if (!confirm('Are you sure you want to delete this alarm?')) return; fetch(`/api/alarms.php?action=delete&id=${id}`, { method: 'GET' }) .then(response => response.json()) .then(data => { if (data.success) { document.querySelector(`li[data-id='${id}']`).remove(); if (alarmsList.children.length === 0) { alarmsList.innerHTML = '
  • No alarms set yet.
  • '; } } else { alert('Error: ' + (data.error || 'Could not delete alarm.')); } }); }; // Handle toggling an alarm's active state const handleToggleAlarm = (id, isActive) => { const formData = new FormData(); formData.append('id', id); formData.append('is_active', isActive ? 1 : 0); fetch('/api/alarms.php?action=toggle', { method: 'POST', body: formData }).then(response => response.json()) .then(data => { if (!data.success) { alert('Error updating alarm status.'); // Revert the toggle switch if the server update fails const toggleInput = document.getElementById(`toggle-${id}`); if(toggleInput) { toggleInput.checked = !isActive; } } }); }; // Function to check for due alarms const checkAlarms = () => { fetch('/api/alarms.php?action=check') .then(response => response.json()) .then(data => { if (data.success && data.alarms && data.alarms.length > 0) { data.alarms.forEach(alarm => { showNotification(alarm); // Update the toggle on the main page to off const alarmToggle = document.querySelector(`#toggle-${alarm.id}`); if (alarmToggle) { alarmToggle.checked = false; } }); } }); }; // Function to show notification const showNotification = (alarm) => { const alarmTime = new Date(`1970-01-01T${alarm.alarm_time}`).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); const notificationTitle = `Alarm: ${alarm.label || alarmTime}`; const notificationBody = 'Time to write your notes. Click here!'; const bellIcon = '/assets/images/bell.png'; const alarmSoundSrc = '/assets/sounds/alarm.mp3.ogg'; // Use browser notification if permission is granted if ('Notification' in window && Notification.permission === 'granted') { const notification = new Notification(notificationTitle, { body: notificationBody, icon: bellIcon, requireInteraction: true }); notification.onclick = () => { window.open(`note.php?id=${alarm.note_id}`, '_blank'); notification.close(); }; // Play sound along with notification const audio = new Audio(alarmSoundSrc); audio.play().catch(e => console.error("Audio playback failed:", e)); } else { // Fallback to modal document.getElementById('alarmModalMessage').textContent = `It's time for your alarm: ${alarm.label || alarmTime}`; const audio = document.getElementById('alarmSound'); if (audio) { audio.src = alarmSoundSrc; // Ensure src is set audio.play().catch(e => console.error("Audio playback failed:", e)); } alarmModal.show(); } dismissAlarmBtn.onclick = () => { const audio = document.getElementById('alarmSound'); if (audio) { audio.pause(); audio.currentTime = 0; } alarmModal.hide(); }; }; // Initial fetch and periodic check fetchAlarms(); setInterval(checkAlarms, 5000); // Check every 5 seconds });