Todo-Apllication / index.html
parthib07's picture
Update index.html
18a5a90 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Student Daily Planner</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
background-image: url('');
background-size: cover;
background-attachment: fixed;
background-position: center;
min-height: 100vh;
}
.glass-card {
background: rgba(255, 255, 255, 0.85);
backdrop-filter: blur(10px);
border-radius: 15px;
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
}
.timeline-item::before {
content: '';
position: absolute;
left: 0;
top: 0;
width: 2px;
height: 100%;
background-color: #4f46e5;
}
.period-card {
transition: all 0.3s ease;
}
.period-card:hover {
transform: translateY(-3px);
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1);
}
.notification-badge {
position: absolute;
top: -8px;
right: -8px;
width: 20px;
height: 20px;
background-color: #ef4444;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 10px;
}
@media (max-width: 768px) {
.routine-grid {
grid-template-columns: repeat(1, minmax(0, 1fr));
}
}
</style>
</head>
<body class="py-8 px-4">
<div class="max-w-6xl mx-auto">
<!-- Header -->
<header class="mb-8 text-center">
<h1 class="text-4xl font-bold text-indigo-800 mb-2">Student Daily Planner</h1>
<p class="text-lg text-indigo-600">Organize your tasks efficiently</p>
<div class="mt-4 flex justify-center space-x-4">
<button id="tasksTab" class="px-4 py-2 bg-indigo-600 text-white rounded-lg font-medium">Tasks</button>
</div>
</header>
<!-- Main Content -->
<main>
<!-- Tasks Section -->
<section id="tasksSection" class="glass-card p-6 mb-8">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-semibold text-indigo-700 flex items-center">
<i class="fas fa-tasks mr-2"></i> Today's Tasks
</h2>
<button id="addTaskBtn" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 flex items-center">
<i class="fas fa-plus mr-2"></i> Add Task
</button>
</div>
<!-- Add Task Modal -->
<div id="taskModal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div class="glass-card p-6 rounded-lg w-full max-w-md">
<div class="flex justify-between items-center mb-4">
<h3 class="text-xl font-semibold text-indigo-700">Add New Task</h3>
<button id="closeTaskModal" class="text-gray-500 hover:text-gray-700">
<i class="fas fa-times"></i>
</button>
</div>
<form id="taskForm" class="space-y-4">
<div>
<label for="taskTitle" class="block text-sm font-medium text-gray-700">Task Title</label>
<input type="text" id="taskTitle" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" required>
</div>
<div>
<label for="taskTime" class="block text-sm font-medium text-gray-700">Time</label>
<input type="time" id="taskTime" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" required>
</div>
<div>
<label for="taskTopic" class="block text-sm font-medium text-gray-700">Topic/Details</label>
<input type="text" id="taskTopic" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
</div>
<div>
<label for="taskReminder" class="block text-sm font-medium text-gray-700">Reminder Before (minutes)</label>
<select id="taskReminder" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border">
<option value="5">5 minutes</option>
<option value="10" selected>10 minutes</option>
<option value="15">15 minutes</option>
</select>
</div>
<div class="flex justify-end space-x-3">
<button type="button" id="cancelTask" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300">Cancel</button>
<button type="submit" class="px-4 py-2 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700">Save Task</button>
</div>
</form>
</div>
</div>
<!-- Tasks Timeline -->
<div id="tasksContainer" class="space-y-4">
<!-- Sample tasks will be inserted here by JavaScript -->
<div class="text-center py-8 text-gray-500" id="noTasksMessage">
<i class="fas fa-clipboard-list text-4xl mb-2"></i>
<p>No tasks added yet. Click "Add Task" to get started!</p>
</div>
</div>
</section>
<script>
// DOM Elements
const tasksTab = document.getElementById('tasksTab');
const routineTab = document.getElementById('routineTab');
const tasksSection = document.getElementById('tasksSection');
const routineSection = document.getElementById('routineSection');
const addTaskBtn = document.getElementById('addTaskBtn');
const taskModal = document.getElementById('taskModal');
const closeTaskModal = document.getElementById('closeTaskModal');
const cancelTask = document.getElementById('cancelTask');
const taskForm = document.getElementById('taskForm');
const tasksContainer = document.getElementById('tasksContainer');
const noTasksMessage = document.getElementById('noTasksMessage');
const addDayBtn = document.getElementById('addDayBtn');
const dayModal = document.getElementById('dayModal');
const closeDayModal = document.getElementById('closeDayModal');
const cancelDay = document.getElementById('cancelDay');
const dayForm = document.getElementById('dayForm');
const periodsModal = document.getElementById('periodsModal');
const closePeriodsModal = document.getElementById('closePeriodsModal');
const cancelPeriods = document.getElementById('cancelPeriods');
const periodsForm = document.getElementById('periodsForm');
const periodsContainer = document.getElementById('periodsContainer');
const routineContainer = document.getElementById('routineContainer');
const noRoutineMessage = document.getElementById('noRoutineMessage');
const periodsModalTitle = document.getElementById('periodsModalTitle');
// Data
let tasks = JSON.parse(localStorage.getItem('tasks')) || [];
let routine = JSON.parse(localStorage.getItem('routine')) || {};
let currentDay = '';
let notificationTimeouts = {};
// Initialize
document.addEventListener('DOMContentLoaded', () => {
renderTasks();
renderRoutine();
checkForNotifications();
});
// Tab Navigation
tasksTab.addEventListener('click', () => {
tasksSection.classList.remove('hidden');
routineSection.classList.add('hidden');
tasksTab.classList.add('bg-indigo-600', 'text-white');
tasksTab.classList.remove('bg-white', 'text-indigo-600');
routineTab.classList.add('bg-white', 'text-indigo-600');
routineTab.classList.remove('bg-indigo-600', 'text-white');
});
routineTab.addEventListener('click', () => {
routineSection.classList.remove('hidden');
tasksSection.classList.add('hidden');
routineTab.classList.add('bg-indigo-600', 'text-white');
routineTab.classList.remove('bg-white', 'text-indigo-600');
tasksTab.classList.add('bg-white', 'text-indigo-600');
tasksTab.classList.remove('bg-indigo-600', 'text-white');
});
// Task Modal
addTaskBtn.addEventListener('click', () => {
taskModal.classList.remove('hidden');
});
closeTaskModal.addEventListener('click', () => {
taskModal.classList.add('hidden');
});
cancelTask.addEventListener('click', () => {
taskModal.classList.add('hidden');
});
// Task Form Submission
taskForm.addEventListener('submit', (e) => {
e.preventDefault();
const title = document.getElementById('taskTitle').value;
const time = document.getElementById('taskTime').value;
const topic = document.getElementById('taskTopic').value;
const reminder = parseInt(document.getElementById('taskReminder').value);
const newTask = {
id: Date.now(),
title,
time,
topic,
reminder,
completed: false
};
tasks.push(newTask);
saveTasks();
renderTasks();
scheduleNotification(newTask);
taskForm.reset();
taskModal.classList.add('hidden');
});
// Day Modal
addDayBtn.addEventListener('click', () => {
dayModal.classList.remove('hidden');
});
closeDayModal.addEventListener('click', () => {
dayModal.classList.add('hidden');
});
cancelDay.addEventListener('click', () => {
dayModal.classList.add('hidden');
});
// Day Form Submission
dayForm.addEventListener('submit', (e) => {
e.preventDefault();
const day = document.getElementById('daySelect').value;
const periodCount = parseInt(document.getElementById('periodCount').value);
currentDay = day;
periodsModalTitle.textContent = `Add Periods for ${day}`;
// Clear previous inputs
periodsContainer.innerHTML = '';
// Create inputs for each period
for (let i = 1; i <= periodCount; i++) {
const periodDiv = document.createElement('div');
periodDiv.className = 'space-y-2 p-4 bg-gray-50 rounded-lg mb-4';
periodDiv.innerHTML = `
<h4 class="font-medium text-indigo-600">Period ${i}</h4>
<div>
<label for="subject-${i}" class="block text-sm font-medium text-gray-700">Subject</label>
<input type="text" id="subject-${i}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" required>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="startTime-${i}" class="block text-sm font-medium text-gray-700">Start Time</label>
<input type="time" id="startTime-${i}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" required>
</div>
<div>
<label for="endTime-${i}" class="block text-sm font-medium text-gray-700">End Time</label>
<input type="time" id="endTime-${i}" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" required>
</div>
</div>
`;
periodsContainer.appendChild(periodDiv);
}
dayModal.classList.add('hidden');
periodsModal.classList.remove('hidden');
});
// Periods Form Submission
periodsForm.addEventListener('submit', (e) => {
e.preventDefault();
const periodCount = parseInt(document.getElementById('periodCount').value);
const periods = [];
for (let i = 1; i <= periodCount; i++) {
const subject = document.getElementById(`subject-${i}`).value;
const startTime = document.getElementById(`startTime-${i}`).value;
const endTime = document.getElementById(`endTime-${i}`).value;
periods.push({
number: i,
subject,
startTime,
endTime
});
}
routine[currentDay] = periods;
saveRoutine();
renderRoutine();
periodsModal.classList.add('hidden');
dayForm.reset();
});
closePeriodsModal.addEventListener('click', () => {
periodsModal.classList.add('hidden');
});
cancelPeriods.addEventListener('click', () => {
periodsModal.classList.add('hidden');
});
// Render Tasks
function renderTasks() {
if (tasks.length === 0) {
noTasksMessage.classList.remove('hidden');
tasksContainer.innerHTML = '';
return;
}
noTasksMessage.classList.add('hidden');
// Sort tasks by time
tasks.sort((a, b) => {
return a.time.localeCompare(b.time);
});
tasksContainer.innerHTML = '';
tasks.forEach(task => {
const taskElement = document.createElement('div');
taskElement.className = 'relative pl-8 timeline-item';
taskElement.dataset.id = task.id;
const timeParts = task.time.split(':');
const formattedTime = `${parseInt(timeParts[0]) > 12 ? parseInt(timeParts[0]) - 12 : timeParts[0]}:${timeParts[1]} ${parseInt(timeParts[0]) >= 12 ? 'PM' : 'AM'}`;
taskElement.innerHTML = `
<div class="bg-white p-4 rounded-lg shadow-sm border-l-4 border-indigo-500 relative">
<div class="absolute -left-3 top-4 w-6 h-6 rounded-full bg-indigo-500 flex items-center justify-center text-white">
<i class="fas fa-clock text-xs"></i>
</div>
<div class="flex justify-between items-start">
<div>
<h3 class="font-medium ${task.completed ? 'line-through text-gray-400' : 'text-gray-800'}">${task.title}</h3>
<p class="text-sm text-gray-500">${formattedTime}</p>
${task.topic ? `<p class="text-sm text-gray-600 mt-1"><span class="font-medium">Topic:</span> ${task.topic}</p>` : ''}
</div>
<div class="flex space-x-2">
<button class="edit-task p-2 text-indigo-600 hover:text-indigo-800">
<i class="fas fa-edit"></i>
</button>
<button class="delete-task p-2 text-red-600 hover:text-red-800">
<i class="fas fa-trash"></i>
</button>
<button class="complete-task p-2 ${task.completed ? 'text-green-600' : 'text-gray-400 hover:text-green-600'}">
<i class="fas fa-check"></i>
</button>
</div>
</div>
</div>
`;
tasksContainer.appendChild(taskElement);
});
// Add event listeners for task actions
document.querySelectorAll('.edit-task').forEach(btn => {
btn.addEventListener('click', (e) => {
const taskId = parseInt(e.target.closest('.timeline-item').dataset.id);
editTask(taskId);
});
});
document.querySelectorAll('.delete-task').forEach(btn => {
btn.addEventListener('click', (e) => {
const taskId = parseInt(e.target.closest('.timeline-item').dataset.id);
deleteTask(taskId);
});
});
document.querySelectorAll('.complete-task').forEach(btn => {
btn.addEventListener('click', (e) => {
const taskId = parseInt(e.target.closest('.timeline-item').dataset.id);
toggleTaskComplete(taskId);
});
});
}
// Render Routine
function renderRoutine() {
if (Object.keys(routine).length === 0) {
noRoutineMessage.classList.remove('hidden');
routineContainer.innerHTML = '';
return;
}
noRoutineMessage.classList.add('hidden');
routineContainer.innerHTML = '';
Object.entries(routine).forEach(([day, periods]) => {
const dayCard = document.createElement('div');
dayCard.className = 'bg-white p-4 rounded-lg shadow-sm border-t-4 border-indigo-500';
let periodsHTML = '';
periods.forEach(period => {
periodsHTML += `
<div class="period-card bg-gray-50 p-3 rounded-lg mb-3 relative">
<div class="flex justify-between items-center">
<h4 class="font-medium text-indigo-700">Period ${period.number}: ${period.subject}</h4>
<div class="flex space-x-2">
<button class="edit-period p-1 text-indigo-600 hover:text-indigo-800" data-day="${day}" data-period="${period.number}">
<i class="fas fa-edit text-sm"></i>
</button>
<button class="delete-period p-1 text-red-600 hover:text-red-800" data-day="${day}" data-period="${period.number}">
<i class="fas fa-trash text-sm"></i>
</button>
</div>
</div>
<p class="text-sm text-gray-600 mt-1">
<i class="far fa-clock mr-1"></i> ${formatTime(period.startTime)} - ${formatTime(period.endTime)}
</p>
</div>
`;
});
dayCard.innerHTML = `
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold text-indigo-800">${day}</h3>
<div class="flex space-x-2">
<button class="add-period p-1 text-indigo-600 hover:text-indigo-800" data-day="${day}">
<i class="fas fa-plus-circle"></i>
</button>
<button class="delete-day p-1 text-red-600 hover:text-red-800" data-day="${day}">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<div class="periods-container">
${periodsHTML}
</div>
`;
routineContainer.appendChild(dayCard);
});
// Add event listeners for routine actions
document.querySelectorAll('.add-period').forEach(btn => {
btn.addEventListener('click', (e) => {
const day = e.target.closest('.add-period').dataset.day;
addPeriod(day);
});
});
document.querySelectorAll('.edit-period').forEach(btn => {
btn.addEventListener('click', (e) => {
const day = e.target.closest('.edit-period').dataset.day;
const periodNum = parseInt(e.target.closest('.edit-period').dataset.period);
editPeriod(day, periodNum);
});
});
document.querySelectorAll('.delete-period').forEach(btn => {
btn.addEventListener('click', (e) => {
const day = e.target.closest('.delete-period').dataset.day;
const periodNum = parseInt(e.target.closest('.delete-period').dataset.period);
deletePeriod(day, periodNum);
});
});
document.querySelectorAll('.delete-day').forEach(btn => {
btn.addEventListener('click', (e) => {
const day = e.target.closest('.delete-day').dataset.day;
deleteDay(day);
});
});
}
// Task Actions
function editTask(id) {
const task = tasks.find(t => t.id === id);
if (!task) return;
document.getElementById('taskTitle').value = task.title;
document.getElementById('taskTime').value = task.time;
document.getElementById('taskTopic').value = task.topic || '';
document.getElementById('taskReminder').value = task.reminder;
// Remove the task from the array
tasks = tasks.filter(t => t.id !== id);
saveTasks();
// Open the modal to edit
taskModal.classList.remove('hidden');
}
function deleteTask(id) {
if (confirm('Are you sure you want to delete this task?')) {
tasks = tasks.filter(t => t.id !== id);
saveTasks();
renderTasks();
// Clear any scheduled notification
if (notificationTimeouts[id]) {
clearTimeout(notificationTimeouts[id]);
delete notificationTimeouts[id];
}
}
}
function toggleTaskComplete(id) {
const task = tasks.find(t => t.id === id);
if (task) {
task.completed = !task.completed;
saveTasks();
renderTasks();
}
}
// Routine Actions
function addPeriod(day) {
currentDay = day;
periodsModalTitle.textContent = `Add Period to ${day}`;
// Clear previous inputs
periodsContainer.innerHTML = '';
const periodDiv = document.createElement('div');
periodDiv.className = 'space-y-2 p-4 bg-gray-50 rounded-lg mb-4';
const nextPeriodNumber = routine[day] ? routine[day].length + 1 : 1;
periodDiv.innerHTML = `
<h4 class="font-medium text-indigo-600">New Period</h4>
<div>
<label for="subject-new" class="block text-sm font-medium text-gray-700">Subject</label>
<input type="text" id="subject-new" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" required>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="startTime-new" class="block text-sm font-medium text-gray-700">Start Time</label>
<input type="time" id="startTime-new" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" required>
</div>
<div>
<label for="endTime-new" class="block text-sm font-medium text-gray-700">End Time</label>
<input type="time" id="endTime-new" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" required>
</div>
</div>
`;
periodsContainer.appendChild(periodDiv);
// Change the form submit handler for adding a single period
periodsForm.removeEventListener('submit', handlePeriodsFormSubmit);
periodsForm.addEventListener('submit', handleAddPeriodSubmit);
periodsModal.classList.remove('hidden');
function handleAddPeriodSubmit(e) {
e.preventDefault();
const subject = document.getElementById('subject-new').value;
const startTime = document.getElementById('startTime-new').value;
const endTime = document.getElementById('endTime-new').value;
if (!routine[day]) {
routine[day] = [];
}
routine[day].push({
number: nextPeriodNumber,
subject,
startTime,
endTime
});
saveRoutine();
renderRoutine();
periodsModal.classList.add('hidden');
periodsForm.reset();
// Restore the original form handler
periodsForm.removeEventListener('submit', handleAddPeriodSubmit);
periodsForm.addEventListener('submit', handlePeriodsFormSubmit);
}
}
function editPeriod(day, periodNum) {
const period = routine[day].find(p => p.number === periodNum);
if (!period) return;
currentDay = day;
periodsModalTitle.textContent = `Edit Period ${periodNum} for ${day}`;
// Clear previous inputs
periodsContainer.innerHTML = '';
const periodDiv = document.createElement('div');
periodDiv.className = 'space-y-2 p-4 bg-gray-50 rounded-lg mb-4';
periodDiv.innerHTML = `
<h4 class="font-medium text-indigo-600">Period ${periodNum}</h4>
<div>
<label for="subject-edit" class="block text-sm font-medium text-gray-700">Subject</label>
<input type="text" id="subject-edit" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" value="${period.subject}" required>
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label for="startTime-edit" class="block text-sm font-medium text-gray-700">Start Time</label>
<input type="time" id="startTime-edit" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" value="${period.startTime}" required>
</div>
<div>
<label for="endTime-edit" class="block text-sm font-medium text-gray-700">End Time</label>
<input type="time" id="endTime-edit" class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 p-2 border" value="${period.endTime}" required>
</div>
</div>
`;
periodsContainer.appendChild(periodDiv);
// Change the form submit handler for editing a single period
periodsForm.removeEventListener('submit', handlePeriodsFormSubmit);
periodsForm.addEventListener('submit', handleEditPeriodSubmit);
periodsModal.classList.remove('hidden');
function handleEditPeriodSubmit(e) {
e.preventDefault();
const subject = document.getElementById('subject-edit').value;
const startTime = document.getElementById('startTime-edit').value;
const endTime = document.getElementById('endTime-edit').value;
const periodIndex = routine[day].findIndex(p => p.number === periodNum);
if (periodIndex !== -1) {
routine[day][periodIndex] = {
number: periodNum,
subject,
startTime,
endTime
};
}
saveRoutine();
renderRoutine();
periodsModal.classList.add('hidden');
periodsForm.reset();
// Restore the original form handler
periodsForm.removeEventListener('submit', handleEditPeriodSubmit);
periodsForm.addEventListener('submit', handlePeriodsFormSubmit);
}
}
function deletePeriod(day, periodNum) {
if (confirm('Are you sure you want to delete this period?')) {
routine[day] = routine[day].filter(p => p.number !== periodNum);
// Renumber remaining periods
routine[day].forEach((p, index) => {
p.number = index + 1;
});
saveRoutine();
renderRoutine();
}
}
function deleteDay(day) {
if (confirm(`Are you sure you want to delete all periods for ${day}?`)) {
delete routine[day];
saveRoutine();
renderRoutine();
}
}
function handlePeriodsFormSubmit(e) {
e.preventDefault();
const periodCount = parseInt(document.getElementById('periodCount').value);
const periods = [];
for (let i = 1; i <= periodCount; i++) {
const subject = document.getElementById(`subject-${i}`).value;
const startTime = document.getElementById(`startTime-${i}`).value;
const endTime = document.getElementById(`endTime-${i}`).value;
periods.push({
number: i,
subject,
startTime,
endTime
});
}
routine[currentDay] = periods;
saveRoutine();
renderRoutine();
periodsModal.classList.add('hidden');
dayForm.reset();
}
// Helper Functions
function saveTasks() {
localStorage.setItem('tasks', JSON.stringify(tasks));
}
function saveRoutine() {
localStorage.setItem('routine', JSON.stringify(routine));
}
function formatTime(timeStr) {
if (!timeStr) return '';
const [hours, minutes] = timeStr.split(':');
const hourNum = parseInt(hours);
const ampm = hourNum >= 12 ? 'PM' : 'AM';
const displayHour = hourNum % 12 || 12;
return `${displayHour}:${minutes} ${ampm}`;
}
function scheduleNotification(task) {
if (!('Notification' in window)) {
console.log('This browser does not support desktop notification');
return;
}
// Check if notification permission is already granted
if (Notification.permission !== 'granted') {
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
createNotificationTimeout(task);
}
});
} else {
createNotificationTimeout(task);
}
}
function createNotificationTimeout(task) {
const taskTime = new Date();
const [hours, minutes] = task.time.split(':');
taskTime.setHours(parseInt(hours));
taskTime.setMinutes(parseInt(minutes));
const reminderTime = new Date(taskTime.getTime() - task.reminder * 60000);
const now = new Date();
// Only schedule if the reminder time is in the future
if (reminderTime > now) {
const timeout = reminderTime.getTime() - now.getTime();
notificationTimeouts[task.id] = setTimeout(() => {
showNotification(task);
}, timeout);
}
}
function showNotification(task) {
const notification = new Notification('Task Reminder', {
body: `It's time to ${task.title}${task.topic ? ` (${task.topic})` : ''}`,
icon: 'https://cdn-icons-png.flaticon.com/512/3652/3652191.png'
});
notification.onclick = () => {
window.focus();
};
}
function checkForNotifications() {
tasks.forEach(task => {
if (!task.completed) {
scheduleNotification(task);
}
});
}
</script>
</body>
</html>