Spaces:
Running
Running
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Study Manager</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> | |
.tab-content { | |
display: none; | |
} | |
.tab-content.active { | |
display: block; | |
animation: fadeIn 0.5s; | |
} | |
@keyframes fadeIn { | |
from { opacity: 0; } | |
to { opacity: 1; } | |
} | |
.progress-bar { | |
height: 20px; | |
border-radius: 10px; | |
background-color: #e0e0e0; | |
overflow: hidden; | |
} | |
.progress-fill { | |
height: 100%; | |
border-radius: 10px; | |
background-color: #4CAF50; | |
transition: width 0.3s ease; | |
} | |
.session-cell { | |
min-height: 60px; | |
position: relative; | |
} | |
.session-content { | |
position: absolute; | |
top: 0; | |
left: 0; | |
right: 0; | |
bottom: 0; | |
padding: 4px; | |
overflow: hidden; | |
text-overflow: ellipsis; | |
} | |
.draggable { | |
cursor: move; | |
} | |
.dropzone { | |
min-height: 60px; | |
border: 2px dashed #ccc; | |
border-radius: 5px; | |
margin-bottom: 10px; | |
padding: 10px; | |
} | |
.dropzone.highlight { | |
border-color: #4CAF50; | |
background-color: #f0fff0; | |
} | |
</style> | |
</head> | |
<body class="bg-gray-100 font-sans"> | |
<div class="container mx-auto px-4 py-8 max-w-6xl"> | |
<header class="mb-8 text-center"> | |
<h1 class="text-4xl font-bold text-indigo-700 mb-2">Study Manager</h1> | |
<p class="text-gray-600">Organize your academic life efficiently</p> | |
</header> | |
<div class="bg-white rounded-lg shadow-lg overflow-hidden mb-8"> | |
<div class="flex border-b border-gray-200"> | |
<button class="tab-btn py-4 px-6 font-medium text-gray-600 hover:text-indigo-600 hover:bg-gray-50 transition duration-300 active" data-tab="tasks"> | |
<i class="fas fa-tasks mr-2"></i>Tasks | |
</button> | |
<button class="tab-btn py-4 px-6 font-medium text-gray-600 hover:text-indigo-600 hover:bg-gray-50 transition duration-300" data-tab="lessons"> | |
<i class="fas fa-book mr-2"></i>Lessons | |
</button> | |
<button class="tab-btn py-4 px-6 font-medium text-gray-600 hover:text-indigo-600 hover:bg-gray-50 transition duration-300" data-tab="weekly-plans"> | |
<i class="fas fa-calendar-week mr-2"></i>Weekly Plans | |
</button> | |
<button class="tab-btn py-4 px-6 font-medium text-gray-600 hover:text-indigo-600 hover:bg-gray-50 transition duration-300" data-tab="timetable"> | |
<i class="fas fa-calendar-alt mr-2"></i>Timetable | |
</button> | |
<button class="tab-btn py-4 px-6 font-medium text-gray-600 hover:text-indigo-600 hover:bg-gray-50 transition duration-300" data-tab="exams"> | |
<i class="fas fa-file-alt mr-2"></i>Exams | |
</button> | |
</div> | |
<!-- Tasks Tab --> | |
<div id="tasks" class="tab-content active p-6"> | |
<div class="mb-6"> | |
<h2 class="text-2xl font-semibold text-gray-800 mb-4">My Tasks</h2> | |
<div class="flex mb-4"> | |
<input type="text" id="new-task" placeholder="Add a new task..." class="flex-grow px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
<button id="add-task" class="bg-indigo-600 text-white px-4 py-2 rounded-r-lg hover:bg-indigo-700 transition duration-300"> | |
<i class="fas fa-plus mr-1"></i> Add | |
</button> | |
</div> | |
<div id="tasks-container" class="space-y-3"> | |
<!-- Tasks will be added here --> | |
</div> | |
</div> | |
</div> | |
<!-- Lessons Tab --> | |
<div id="lessons" class="tab-content p-6"> | |
<div class="mb-6"> | |
<h2 class="text-2xl font-semibold text-gray-800 mb-4">My Lessons</h2> | |
<div class="flex mb-4"> | |
<input type="text" id="new-lesson" placeholder="Add a new lesson..." class="flex-grow px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
<button id="add-lesson" class="bg-indigo-600 text-white px-4 py-2 rounded-r-lg hover:bg-indigo-700 transition duration-300"> | |
<i class="fas fa-plus mr-1"></i> Add | |
</button> | |
</div> | |
<div id="lessons-container" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> | |
<!-- Lessons will be added here --> | |
</div> | |
</div> | |
</div> | |
<!-- Weekly Plans Tab --> | |
<div id="weekly-plans" class="tab-content p-6"> | |
<h2 class="text-2xl font-semibold text-gray-800 mb-6">Weekly Study Plan</h2> | |
<div class="mb-6"> | |
<div class="flex items-center mb-4"> | |
<input type="text" id="new-session" placeholder="Enter session content..." class="flex-grow px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
<button id="add-session" class="bg-indigo-600 text-white px-4 py-2 rounded-r-lg hover:bg-indigo-700 transition duration-300"> | |
<i class="fas fa-plus mr-1"></i> Create Session | |
</button> | |
</div> | |
<div id="sessions-pool" class="dropzone grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3 mb-6 p-4"> | |
<p class="col-span-full text-gray-500 text-sm">Drag sessions from here to the weekly plan below</p> | |
<!-- Sessions will be added here --> | |
</div> | |
</div> | |
<div class="overflow-x-auto"> | |
<div class="flex space-x-4 mb-6"> | |
<button class="day-btn px-4 py-2 bg-indigo-100 text-indigo-700 rounded-lg font-medium" data-day="sunday">Sunday</button> | |
<button class="day-btn px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-medium" data-day="monday">Monday</button> | |
<button class="day-btn px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-medium" data-day="tuesday">Tuesday</button> | |
<button class="day-btn px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-medium" data-day="wednesday">Wednesday</button> | |
<button class="day-btn px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-medium" data-day="thursday">Thursday</button> | |
</div> | |
<div id="weekly-plan-container"> | |
<!-- Sunday Plan (default visible) --> | |
<div id="sunday-plan" class="day-plan"> | |
<table class="min-w-full bg-white rounded-lg overflow-hidden"> | |
<thead class="bg-gray-100"> | |
<tr> | |
<th class="py-3 px-4 text-left text-gray-700 font-semibold">Session</th> | |
<th class="py-3 px-4 text-left text-gray-700 font-semibold">Time</th> | |
<th class="py-3 px-4 text-left text-gray-700 font-semibold">Content</th> | |
</tr> | |
</thead> | |
<tbody class="divide-y divide-gray-200"> | |
<!-- Sessions will be added here --> | |
</tbody> | |
</table> | |
</div> | |
<!-- Other days' plans (hidden by default) --> | |
<div id="monday-plan" class="day-plan hidden"></div> | |
<div id="tuesday-plan" class="day-plan hidden"></div> | |
<div id="wednesday-plan" class="day-plan hidden"></div> | |
<div id="thursday-plan" class="day-plan hidden"></div> | |
</div> | |
</div> | |
</div> | |
<!-- Timetable Tab --> | |
<div id="timetable" class="tab-content p-6"> | |
<h2 class="text-2xl font-semibold text-gray-800 mb-6">Weekly Timetable</h2> | |
<div class="overflow-x-auto"> | |
<table class="min-w-full bg-white rounded-lg overflow-hidden shadow"> | |
<thead class="bg-indigo-600 text-white"> | |
<tr> | |
<th class="py-3 px-4 text-left">Time</th> | |
<th class="py-3 px-4 text-left">Sunday</th> | |
<th class="py-3 px-4 text-left">Monday</th> | |
<th class="py-3 px-4 text-left">Tuesday</th> | |
<th class="py-3 px-4 text-left">Wednesday</th> | |
<th class="py-3 px-4 text-left">Thursday</th> | |
</tr> | |
</thead> | |
<tbody class="divide-y divide-gray-200"> | |
<!-- Timetable rows will be added here --> | |
</tbody> | |
</table> | |
</div> | |
<div class="mt-6"> | |
<h3 class="text-lg font-medium text-gray-800 mb-3">Add New Subject</h3> | |
<div class="flex flex-wrap gap-4"> | |
<select id="timetable-day" class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
<option value="sunday">Sunday</option> | |
<option value="monday">Monday</option> | |
<option value="tuesday">Tuesday</option> | |
<option value="wednesday">Wednesday</option> | |
<option value="thursday">Thursday</option> | |
</select> | |
<select id="timetable-session" class="px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
<option value="1">Session 1</option> | |
<option value="2">Session 2</option> | |
<option value="3">Session 3</option> | |
<option value="4">Session 4</option> | |
<option value="5">Session 5</option> | |
<option value="6">Session 6</option> | |
<option value="7">Session 7</option> | |
</select> | |
<input type="text" id="timetable-subject" placeholder="Subject name" class="flex-grow px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
<button id="add-timetable-subject" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition duration-300"> | |
<i class="fas fa-plus mr-1"></i> Add Subject | |
</button> | |
</div> | |
</div> | |
</div> | |
<!-- Exams Tab --> | |
<div id="exams" class="tab-content p-6"> | |
<h2 class="text-2xl font-semibold text-gray-800 mb-6">My Exams</h2> | |
<div class="mb-6 bg-indigo-50 p-4 rounded-lg"> | |
<h3 class="text-lg font-medium text-indigo-800 mb-3">Add New Exam</h3> | |
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4"> | |
<div> | |
<label for="exam-name" class="block text-sm font-medium text-gray-700 mb-1">Exam Name</label> | |
<input type="text" id="exam-name" placeholder="e.g. Math Final" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
</div> | |
<div> | |
<label for="exam-date" class="block text-sm font-medium text-gray-700 mb-1">Exam Date</label> | |
<input type="date" id="exam-date" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
</div> | |
<div> | |
<label for="exam-time" class="block text-sm font-medium text-gray-700 mb-1">Exam Time</label> | |
<input type="time" id="exam-time" class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500"> | |
</div> | |
<div class="flex items-end"> | |
<button id="add-exam" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 transition duration-300 w-full"> | |
<i class="fas fa-plus mr-1"></i> Add Exam | |
</button> | |
</div> | |
</div> | |
</div> | |
<div id="exams-container" class="space-y-6"> | |
<!-- Exams will be added here --> | |
</div> | |
</div> | |
</div> | |
</div> | |
<script> | |
// Tab switching functionality | |
document.querySelectorAll('.tab-btn').forEach(btn => { | |
btn.addEventListener('click', () => { | |
// Remove active class from all tabs and buttons | |
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active')); | |
document.querySelectorAll('.tab-content').forEach(tab => tab.classList.remove('active')); | |
// Add active class to clicked tab and button | |
btn.classList.add('active'); | |
const tabId = btn.getAttribute('data-tab'); | |
document.getElementById(tabId).classList.add('active'); | |
}); | |
}); | |
// Day switching for weekly plans | |
document.querySelectorAll('.day-btn').forEach(btn => { | |
btn.addEventListener('click', () => { | |
// Remove active class from all day buttons | |
document.querySelectorAll('.day-btn').forEach(b => { | |
b.classList.remove('bg-indigo-100', 'text-indigo-700'); | |
b.classList.add('bg-gray-100', 'text-gray-700'); | |
}); | |
// Add active class to clicked button | |
btn.classList.remove('bg-gray-100', 'text-gray-700'); | |
btn.classList.add('bg-indigo-100', 'text-indigo-700'); | |
// Hide all day plans | |
document.querySelectorAll('.day-plan').forEach(plan => plan.classList.add('hidden')); | |
// Show selected day plan | |
const day = btn.getAttribute('data-day'); | |
document.getElementById(`${day}-plan`).classList.remove('hidden'); | |
}); | |
}); | |
// Tasks functionality | |
const tasksContainer = document.getElementById('tasks-container'); | |
const addTaskBtn = document.getElementById('add-task'); | |
const newTaskInput = document.getElementById('new-task'); | |
function addTask(taskText) { | |
if (!taskText.trim()) return; | |
const taskId = 'task-' + Date.now(); | |
const taskElement = document.createElement('div'); | |
taskElement.className = 'flex items-center justify-between bg-white p-4 rounded-lg shadow-sm border border-gray-200'; | |
taskElement.id = taskId; | |
taskElement.innerHTML = ` | |
<div class="flex items-center"> | |
<input type="checkbox" class="mr-3 h-5 w-5 text-indigo-600 rounded focus:ring-indigo-500"> | |
<span class="task-text">${taskText}</span> | |
</div> | |
<button class="delete-task text-gray-400 hover:text-red-500 transition duration-300"> | |
<i class="fas fa-trash"></i> | |
</button> | |
`; | |
tasksContainer.appendChild(taskElement); | |
// Add event listeners | |
const checkbox = taskElement.querySelector('input[type="checkbox"]'); | |
checkbox.addEventListener('change', function() { | |
const taskTextElement = taskElement.querySelector('.task-text'); | |
if (this.checked) { | |
taskTextElement.classList.add('line-through', 'text-gray-400'); | |
} else { | |
taskTextElement.classList.remove('line-through', 'text-gray-400'); | |
} | |
}); | |
const deleteBtn = taskElement.querySelector('.delete-task'); | |
deleteBtn.addEventListener('click', function() { | |
tasksContainer.removeChild(taskElement); | |
}); | |
newTaskInput.value = ''; | |
} | |
addTaskBtn.addEventListener('click', () => addTask(newTaskInput.value)); | |
newTaskInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') addTask(newTaskInput.value); | |
}); | |
// Lessons functionality | |
const lessonsContainer = document.getElementById('lessons-container'); | |
const addLessonBtn = document.getElementById('add-lesson'); | |
const newLessonInput = document.getElementById('new-lesson'); | |
function addLesson(lessonText) { | |
if (!lessonText.trim()) return; | |
const lessonId = 'lesson-' + Date.now(); | |
const lessonElement = document.createElement('div'); | |
lessonElement.className = 'bg-white p-4 rounded-lg shadow-sm border border-gray-200 hover:shadow-md transition duration-300'; | |
lessonElement.id = lessonId; | |
lessonElement.innerHTML = ` | |
<div class="flex justify-between items-start mb-2"> | |
<h3 class="font-medium text-gray-800">${lessonText}</h3> | |
<button class="delete-lesson text-gray-400 hover:text-red-500 transition duration-300"> | |
<i class="fas fa-trash"></i> | |
</button> | |
</div> | |
<div class="flex items-center text-sm text-gray-500"> | |
<span class="mr-3"><i class="far fa-calendar mr-1"></i> Not scheduled</span> | |
<span><i class="far fa-clock mr-1"></i> 0 min</span> | |
</div> | |
`; | |
lessonsContainer.appendChild(lessonElement); | |
// Add event listener for delete button | |
const deleteBtn = lessonElement.querySelector('.delete-lesson'); | |
deleteBtn.addEventListener('click', function() { | |
lessonsContainer.removeChild(lessonElement); | |
}); | |
newLessonInput.value = ''; | |
} | |
addLessonBtn.addEventListener('click', () => addLesson(newLessonInput.value)); | |
newLessonInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') addLesson(newLessonInput.value); | |
}); | |
// Weekly Plans functionality | |
const sessionsPool = document.getElementById('sessions-pool'); | |
const addSessionBtn = document.getElementById('add-session'); | |
const newSessionInput = document.getElementById('new-session'); | |
const sundayPlanTable = document.querySelector('#sunday-plan tbody'); | |
// Initialize empty plans for all days | |
const dayPlans = { | |
sunday: sundayPlanTable, | |
monday: document.querySelector('#monday-plan'), | |
tuesday: document.querySelector('#tuesday-plan'), | |
wednesday: document.querySelector('#wednesday-plan'), | |
thursday: document.querySelector('#thursday-plan') | |
}; | |
// Create tables for other days (similar to Sunday) | |
['monday', 'tuesday', 'wednesday', 'thursday'].forEach(day => { | |
const planElement = dayPlans[day]; | |
planElement.innerHTML = ` | |
<table class="min-w-full bg-white rounded-lg overflow-hidden"> | |
<thead class="bg-gray-100"> | |
<tr> | |
<th class="py-3 px-4 text-left text-gray-700 font-semibold">Session</th> | |
<th class="py-3 px-4 text-left text-gray-700 font-semibold">Time</th> | |
<th class="py-3 px-4 text-left text-gray-700 font-semibold">Content</th> | |
</tr> | |
</thead> | |
<tbody class="divide-y divide-gray-200"></tbody> | |
</table> | |
`; | |
}); | |
function addSessionToPool(sessionText) { | |
if (!sessionText.trim()) return; | |
const sessionId = 'session-' + Date.now(); | |
const sessionElement = document.createElement('div'); | |
sessionElement.className = 'bg-white p-3 rounded-lg shadow-sm border border-gray-200 draggable cursor-move'; | |
sessionElement.id = sessionId; | |
sessionElement.setAttribute('draggable', 'true'); | |
sessionElement.innerHTML = ` | |
<div class="flex justify-between items-center"> | |
<span>${sessionText}</span> | |
<button class="delete-session text-gray-400 hover:text-red-500 transition duration-300"> | |
<i class="fas fa-trash text-sm"></i> | |
</button> | |
</div> | |
`; | |
sessionsPool.appendChild(sessionElement); | |
// Add event listeners | |
const deleteBtn = sessionElement.querySelector('.delete-session'); | |
deleteBtn.addEventListener('click', function(e) { | |
e.stopPropagation(); | |
sessionsPool.removeChild(sessionElement); | |
}); | |
// Drag and drop functionality | |
sessionElement.addEventListener('dragstart', function(e) { | |
e.dataTransfer.setData('text/plain', sessionId); | |
setTimeout(() => { | |
sessionElement.classList.add('opacity-0'); | |
}, 0); | |
}); | |
sessionElement.addEventListener('dragend', function() { | |
sessionElement.classList.remove('opacity-0'); | |
}); | |
newSessionInput.value = ''; | |
} | |
addSessionBtn.addEventListener('click', () => addSessionToPool(newSessionInput.value)); | |
newSessionInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') addSessionToPool(newSessionInput.value); | |
}); | |
// Set up drop zones for each day's plan | |
Object.keys(dayPlans).forEach(day => { | |
const plan = dayPlans[day]; | |
const tbody = day === 'sunday' ? plan : plan.querySelector('tbody'); | |
// Create 7 session rows for each day | |
for (let i = 1; i <= 7; i++) { | |
const row = document.createElement('tr'); | |
row.className = 'hover:bg-gray-50'; | |
row.innerHTML = ` | |
<td class="py-3 px-4">Session ${i}</td> | |
<td class="py-3 px-4"> | |
<input type="time" class="border border-gray-300 rounded px-2 py-1 w-24"> | |
</td> | |
<td class="py-3 px-4 dropzone session-cell" data-session="${i}"></td> | |
`; | |
tbody.appendChild(row); | |
// Set up drop zone for this session | |
const dropzone = row.querySelector('.dropzone'); | |
dropzone.addEventListener('dragover', function(e) { | |
e.preventDefault(); | |
this.classList.add('highlight'); | |
}); | |
dropzone.addEventListener('dragleave', function() { | |
this.classList.remove('highlight'); | |
}); | |
dropzone.addEventListener('drop', function(e) { | |
e.preventDefault(); | |
this.classList.remove('highlight'); | |
const sessionId = e.dataTransfer.getData('text/plain'); | |
const sessionElement = document.getElementById(sessionId); | |
if (sessionElement) { | |
// Clone the session element without the delete button | |
const clonedSession = sessionElement.cloneNode(true); | |
const deleteBtn = clonedSession.querySelector('.delete-session'); | |
if (deleteBtn) deleteBtn.remove(); | |
// Clear the dropzone and append the cloned session | |
this.innerHTML = ''; | |
this.appendChild(clonedSession); | |
// Make the dropped session draggable again | |
clonedSession.setAttribute('draggable', 'true'); | |
clonedSession.addEventListener('dragstart', function(e) { | |
e.dataTransfer.setData('text/plain', sessionId); | |
setTimeout(() => { | |
clonedSession.classList.add('opacity-0'); | |
}, 0); | |
}); | |
clonedSession.addEventListener('dragend', function() { | |
clonedSession.classList.remove('opacity-0'); | |
}); | |
} | |
}); | |
} | |
}); | |
// Timetable functionality | |
const timetableBody = document.querySelector('#timetable tbody'); | |
const addTimetableSubjectBtn = document.getElementById('add-timetable-subject'); | |
const timetableDaySelect = document.getElementById('timetable-day'); | |
const timetableSessionSelect = document.getElementById('timetable-session'); | |
const timetableSubjectInput = document.getElementById('timetable-subject'); | |
// Create 7 rows for the timetable (one for each session) | |
for (let i = 1; i <= 7; i++) { | |
const row = document.createElement('tr'); | |
row.className = 'hover:bg-gray-50'; | |
row.innerHTML = ` | |
<td class="py-3 px-4 font-medium">Session ${i}</td> | |
<td class="py-3 px-4 session-cell" data-day="sunday" data-session="${i}"></td> | |
<td class="py-3 px-4 session-cell" data-day="monday" data-session="${i}"></td> | |
<td class="py-3 px-4 session-cell" data-day="tuesday" data-session="${i}"></td> | |
<td class="py-3 px-4 session-cell" data-day="wednesday" data-session="${i}"></td> | |
<td class="py-3 px-4 session-cell" data-day="thursday" data-session="${i}"></td> | |
`; | |
timetableBody.appendChild(row); | |
} | |
function addTimetableSubject() { | |
const day = timetableDaySelect.value; | |
const session = timetableSessionSelect.value; | |
const subject = timetableSubjectInput.value.trim(); | |
if (!subject) return; | |
// Find the correct cell | |
const cell = document.querySelector(`.session-cell[data-day="${day}"][data-session="${session}"]`); | |
if (cell) { | |
// Create subject element | |
const subjectElement = document.createElement('div'); | |
subjectElement.className = 'bg-indigo-100 text-indigo-800 px-3 py-1 rounded-full inline-flex items-center'; | |
subjectElement.innerHTML = ` | |
<span>${subject}</span> | |
<button class="ml-2 text-indigo-400 hover:text-indigo-700 delete-subject"> | |
<i class="fas fa-times"></i> | |
</button> | |
`; | |
// Add delete functionality | |
const deleteBtn = subjectElement.querySelector('.delete-subject'); | |
deleteBtn.addEventListener('click', function() { | |
cell.removeChild(subjectElement); | |
}); | |
// Add to cell | |
cell.appendChild(subjectElement); | |
timetableSubjectInput.value = ''; | |
} | |
} | |
addTimetableSubjectBtn.addEventListener('click', addTimetableSubject); | |
timetableSubjectInput.addEventListener('keypress', (e) => { | |
if (e.key === 'Enter') addTimetableSubject(); | |
}); | |
// Exams functionality | |
const examsContainer = document.getElementById('exams-container'); | |
const addExamBtn = document.getElementById('add-exam'); | |
const examNameInput = document.getElementById('exam-name'); | |
const examDateInput = document.getElementById('exam-date'); | |
const examTimeInput = document.getElementById('exam-time'); | |
function addExam() { | |
const name = examNameInput.value.trim(); | |
const date = examDateInput.value; | |
const time = examTimeInput.value; | |
if (!name || !date) return; | |
const examId = 'exam-' + Date.now(); | |
const examElement = document.createElement('div'); | |
examElement.className = 'bg-white p-6 rounded-lg shadow-sm border border-gray-200'; | |
examElement.id = examId; | |
// Format date for display | |
const formattedDate = new Date(date).toLocaleDateString('en-US', { | |
weekday: 'long', | |
year: 'numeric', | |
month: 'long', | |
day: 'numeric' | |
}); | |
examElement.innerHTML = ` | |
<div class="flex justify-between items-start mb-4"> | |
<div> | |
<h3 class="text-xl font-semibold text-gray-800">${name}</h3> | |
<div class="text-gray-600 mt-1"> | |
<i class="far fa-calendar-alt mr-1"></i> ${formattedDate} | |
${time ? `<span class="ml-3"><i class="far fa-clock mr-1"></i> ${time}</span>` : ''} | |
</div> | |
</div> | |
<button class="delete-exam text-gray-400 hover:text-red-500 transition duration-300"> | |
<i class="fas fa-trash"></i> | |
</button> | |
</div> | |
<div class="mb-4"> | |
<h4 class="font-medium text-gray-700 mb-2">Materials to Study</h4> | |
<div class="flex mb-2"> | |
<input type="text" class="exam-material-input flex-grow px-4 py-2 border border-gray-300 rounded-l-lg focus:outline-none focus:ring-2 focus:ring-indigo-500" placeholder="Add study material"> | |
<button class="add-material bg-indigo-600 text-white px-4 py-2 rounded-r-lg hover:bg-indigo-700 transition duration-300"> | |
<i class="fas fa-plus"></i> | |
</button> | |
</div> | |
<ul class="materials-list space-y-2 mt-3"> | |
<!-- Materials will be added here --> | |
</ul> | |
</div> | |
<div> | |
<h4 class="font-medium text-gray-700 mb-2">Study Progress</h4> | |
<div class="progress-bar mb-2"> | |
<div class="progress-fill" style="width: 0%"></div> | |
</div> | |
<p class="text-sm text-gray-500 progress-text">0% completed (0 of 0 materials studied)</p> | |
</div> | |
`; | |
examsContainer.appendChild(examElement); | |
// Add event listeners | |
const deleteBtn = examElement.querySelector('.delete-exam'); | |
deleteBtn.addEventListener('click', function() { | |
examsContainer.removeChild(examElement); | |
}); | |
const addMaterialBtn = examElement.querySelector('.add-material'); | |
const materialInput = examElement.querySelector('.exam-material-input'); | |
const materialsList = examElement.querySelector('.materials-list'); | |
const progressFill = examElement.querySelector('.progress-fill'); | |
const progressText = examElement.querySelector('.progress-text'); | |
function updateProgress() { | |
const totalMaterials = materialsList.children.length; | |
const completedMaterials = materialsList.querySelectorAll('input[type="checkbox"]:checked').length; | |
const percentage = totalMaterials > 0 ? Math.round((completedMaterials / totalMaterials) * 100) : 0; | |
progressFill.style.width = `${percentage}%`; | |
progressText.textContent = `${percentage}% completed (${completedMaterials} of ${totalMaterials} materials studied)`; | |
} | |
addMaterialBtn.addEventListener('click', function() { | |
const materialText = materialInput.value.trim(); | |
if (!materialText) return; | |
const materialId = 'material-' + Date.now(); | |
const materialElement = document.createElement('li'); | |
materialElement.className = 'flex items-center'; | |
materialElement.innerHTML = ` | |
<input type="checkbox" class="mr-3 h-5 w-5 text-indigo-600 rounded focus:ring-indigo-500"> | |
<span class="material-text flex-grow">${materialText}</span> | |
<button class="delete-material text-gray-400 hover:text-red-500 transition duration-300 ml-2"> | |
<i class="fas fa-trash"></i> | |
</button> | |
`; | |
materialsList.appendChild(materialElement); | |
materialInput.value = ''; | |
// Add event listeners for the new material | |
const checkbox = materialElement.querySelector('input[type="checkbox"]'); | |
checkbox.addEventListener('change', updateProgress); | |
const deleteMaterialBtn = materialElement.querySelector('.delete-material'); | |
deleteMaterialBtn.addEventListener('click', function() { | |
materialsList.removeChild(materialElement); | |
updateProgress(); | |
}); | |
updateProgress(); | |
}); | |
materialInput.addEventListener('keypress', function(e) { | |
if (e.key === 'Enter') { | |
const materialText = materialInput.value.trim(); | |
if (!materialText) return; | |
const materialId = 'material-' + Date.now(); | |
const materialElement = document.createElement('li'); | |
materialElement.className = 'flex items-center'; | |
materialElement.innerHTML = ` | |
<input type="checkbox" class="mr-3 h-5 w-5 text-indigo-600 rounded focus:ring-indigo-500"> | |
<span class="material-text flex-grow">${materialText}</span> | |
<button class="delete-material text-gray-400 hover:text-red-500 transition duration-300 ml-2"> | |
<i class="fas fa-trash"></i> | |
</button> | |
`; | |
materialsList.appendChild(materialElement); | |
materialInput.value = ''; | |
// Add event listeners for the new material | |
const checkbox = materialElement.querySelector('input[type="checkbox"]'); | |
checkbox.addEventListener('change', updateProgress); | |
const deleteMaterialBtn = materialElement.querySelector('.delete-material'); | |
deleteMaterialBtn.addEventListener('click', function() { | |
materialsList.removeChild(materialElement); | |
updateProgress(); | |
}); | |
updateProgress(); | |
} | |
}); | |
// Clear form | |
examNameInput.value = ''; | |
examDateInput.value = ''; | |
examTimeInput.value = ''; | |
} | |
addExamBtn.addEventListener('click', addExam); | |
</script> | |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=MaroSamrah/study-manager" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> | |
</html> |