35908-vm/assets/js/main.js
2025-11-21 18:15:18 +00:00

229 lines
7.9 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function () {
// --- ELEMENTS ---
const createAlarmForm = document.getElementById('createAlarmForm');
const alarmList = document.getElementById('alarmList');
const noAlarmsMessage = document.getElementById('noAlarmsMessage');
const alarmModalEl = document.getElementById('alarmModal');
const alarmModal = new bootstrap.Modal(alarmModalEl);
const dismissAlarmBtn = document.getElementById('dismissAlarmBtn');
const alarmSound = document.getElementById('alarmSound');
const alarmModalMessage = document.getElementById('alarmModalMessage');
// --- STATE ---
let isAlarmModalShown = false;
// --- FUNCTIONS ---
/**
* Handles the submission of the create alarm form.
*/
const handleCreateAlarm = async (e) => {
e.preventDefault();
const timeInput = document.getElementById('alarmTime');
const labelInput = document.getElementById('alarmLabel');
const formData = new FormData();
formData.append('action', 'create');
formData.append('alarm_time', timeInput.value);
formData.append('label', labelInput.value);
try {
const response = await fetch('api/alarms.php', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.success) {
addAlarmToList(result.id, timeInput.value, labelInput.value);
timeInput.value = '';
labelInput.value = '';
if (noAlarmsMessage) {
noAlarmsMessage.style.display = 'none';
}
} else {
alert('Error: ' + result.message);
}
} catch (error) {
console.error('Failed to create alarm:', error);
alert('An error occurred while creating the alarm.');
}
};
/**
* Handles the click on a delete alarm form.
*/
const handleDeleteAlarm = async (e) => {
if (!e.target.closest('.delete-alarm-form')) return;
e.preventDefault();
const form = e.target.closest('.delete-alarm-form');
const alarmId = form.querySelector('input[name="alarm_id"]').value;
if (!confirm('Are you sure you want to delete this alarm?')) return;
const formData = new FormData(form);
try {
const response = await fetch('api/alarms.php', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.success) {
const listItem = form.closest('li');
listItem.remove();
if (!alarmList.querySelector('li')) {
if (noAlarmsMessage) {
noAlarmsMessage.style.display = 'block';
}
}
} else {
alert('Error: ' + result.message);
}
} catch (error) {
console.error('Failed to delete alarm:', error);
alert('An error occurred while deleting the alarm.');
}
};
/**
* Adds a new alarm item to the DOM.
*/
const addAlarmToList = (id, time, label, isActive = true) => {
const date = new Date(`1970-01-01T${time}`);
const formattedTime = date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true });
const li = document.createElement('li');
li.className = 'list-group-item d-flex justify-content-between align-items-center';
li.dataset.id = id;
li.innerHTML = `
<div class="d-flex align-items-center">
<div class="form-check form-switch me-3">
<input class="form-check-input toggle-alarm-switch" type="checkbox" role="switch" id="toggle-${id}" ${isActive ? 'checked' : ''}>
<label class="form-check-label" for="toggle-${id}"></label>
</div>
<div>
<span class="fw-bold fs-5">${formattedTime}</span>
<span class="text-muted ms-2">${escapeHTML(label)}</span>
</div>
</div>
<form class="delete-alarm-form">
<input type="hidden" name="action" value="delete">
<input type="hidden" name="alarm_id" value="${id}">
<button type="submit" class="btn btn-sm btn-outline-danger">
<i data-feather="trash-2" class="align-text-bottom"></i>
</button>
</form>
`;
alarmList.appendChild(li);
feather.replace();
};
/**
* Handles toggling the active state of an alarm.
*/
const handleToggleAlarm = async (e) => {
if (!e.target.classList.contains('toggle-alarm-switch')) return;
const switchEl = e.target;
const listItem = switchEl.closest('li');
const alarmId = listItem.dataset.id;
const isActive = switchEl.checked ? 1 : 0;
const formData = new FormData();
formData.append('action', 'toggle');
formData.append('alarm_id', alarmId);
formData.append('is_active', isActive);
try {
const response = await fetch('api/alarms.php', {
method: 'POST',
body: formData
});
const result = await response.json();
if (!result.success) {
alert('Error: ' + result.message);
// Revert the switch on failure
switchEl.checked = !switchEl.checked;
}
} catch (error) {
console.error('Failed to toggle alarm:', error);
alert('An error occurred while updating the alarm.');
// Revert the switch on failure
switchEl.checked = !switchEl.checked;
}
};
/**
* Checks the server for any due alarms.
*/
const checkAlarms = async () => {
if (isAlarmModalShown) return; // Don't check if an alarm is already ringing
try {
const response = await fetch('api/alarms.php?action=check');
const result = await response.json();
if (result.success && result.alarms.length > 0) {
const alarm = result.alarms[0];
triggerAlarm(alarm);
}
} catch (error) {
console.error('Error checking alarms:', error);
}
};
/**
* Triggers the visual and audible alarm.
*/
const triggerAlarm = (alarm) => {
isAlarmModalShown = true;
if (alarm.label) {
alarmModalMessage.textContent = alarm.label;
} else {
alarmModalMessage.textContent = 'Time to write your notes.';
}
alarmModal.show();
alarmSound.play().catch(e => console.error("Audio play failed:", e));
};
/**
* Dismisses the alarm and redirects to the note page.
*/
const dismissAlarm = () => {
alarmSound.pause();
alarmSound.currentTime = 0;
alarmModal.hide();
isAlarmModalShown = false;
const today = new Date();
const dateString = today.getFullYear() + '-' + String(today.getMonth() + 1).padStart(2, '0') + '-' + String(today.getDate()).padStart(2, '0');
window.location.href = `note.php?date=${dateString}`;
};
const escapeHTML = (str) => {
const p = document.createElement('p');
p.appendChild(document.createTextNode(str));
return p.innerHTML;
}
// --- EVENT LISTENERS ---
if (createAlarmForm) {
createAlarmForm.addEventListener('submit', handleCreateAlarm);
}
if (alarmList) {
alarmList.addEventListener('click', handleDeleteAlarm);
alarmList.addEventListener('change', handleToggleAlarm);
}
if (dismissAlarmBtn) {
dismissAlarmBtn.addEventListener('click', dismissAlarm);
}
// --- INITIALIZATION ---
setInterval(checkAlarms, 5000); // Check for alarms every 5 seconds
});