JIT
adding buttons for score management and assignment creation in admin portal
Add another button to manage scores & grades that will also show the student's grades and add a button to create assignment that the admin can add and the student will see the assignment that the admin has placed on the student dashboard. I need the full code and all the buttons need to function. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Admin Portal</title> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet"> <style> :root { --primary: #4f46e5; --primary-hover: #4338ca; --error: #ef4444; --gray-light: #f3f4f6; --gray-dark: #6b7280; --white-transparent: rgba(255, 255, 255, 0.85); } body { font-family: 'Inter', sans-serif; background: url("https://scontent.fmnl17-2.fna.fbcdn.net/v/t1.15752-9/486754266_1224005149440673_6902108939050329715_n.jpg?_nc_cat=111&ccb=1-7&_nc_sid=0024fc&_nc_eui2=AeG50dP5j8VNrTBnJACPMCd-kqE1idO8TmiSoTWJ07xOaD9-E6lwaerGMjWUoLCeM8eTxL11fluQ8amwPaauMxYR&_nc_ohc=eyQP1Opy8lEQ7kNvwFaqx9m&_nc_oc=Adn0oApER6Og4knvroCsu298eiyXdreCpe7nB3nY5y_ZXdwCJjLGBaOraukLkZTg9bE&_nc_ad=z-m&_nc_cid=0&_nc_zt=23&_nc_ht=scontent.fmnl17-2.fna&oh=03_Q7cD2QHfdN4hjkX_lAgqbaAgW1CBx97gTVJJw3ZpsTglDhEuCA&oe=68423BF1") no-repeat center center fixed; background-size: cover; display: flex; flex-direction: column; justify-content: center; align-items: center; min-height: 100vh; margin: 0; padding: 20px; } .site-header { text-align: center; margin-bottom: 30px; width: 100%; max-width: 600px; background-color: var(--white-transparent); padding: 20px; border-radius: 12px; box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); } .site-header h1 { font-size: 1.8rem; color: #1a365d; margin-bottom: 5px; font-weight: 600; } .site-header p { font-size: 1rem; color: var(--gray-dark); margin-top: 8px; } .logo-image { width: 120px; height: auto; margin-bottom: 15px; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1)); } .login-container { background: var(--white-transparent); padding: 40px; border-radius: 12px; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15); width: 100%; max-width: 400px; transition: all 0.3s ease; backdrop-filter: blur(4px); } .login-container:hover { box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2); } .logo { text-align: center; margin-bottom: 30px; } .logo h1 { color: var(--primary); font-size: 24px; font-weight: 600; margin: 0; } .logo p { color: var(--gray-dark); margin: 5px 0 0; font-size: 14px; } .form-group { margin-bottom: 20px; } .form-group label { display: block; margin-bottom: 8px; font-size: 14px; font-weight: 500; color: #374151; } input { width: 100%; padding: 12px 16px; border: 1px solid #e5e7eb; border-radius: 8px; font-size: 14px; transition: all 0.2s; box-sizing: border-box; background-color: rgba(255, 255, 255, 0.8); } input:focus { outline: none; border-color: var(--primary); box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1); background-color: white; } button { width: 100%; padding: 12px; background-color: var(--primary); color: white; border: none; border-radius: 8px; font-size: 16px; font-weight: 500; cursor: pointer; transition: all 0.2s; margin-top: 10px; } button:hover { background-color: var(--primary-hover); transform: translateY(-1px); box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); } button:active { transform: translateY(0); } .error-message { color: var(--error); font-size: 14px; margin-top: 15px; text-align: center; height: 20px; } .footer { text-align: center; margin-top: 30px; font-size: 12px; color: var(--gray-dark); } </style> </head> <body> <div class="site-header"> <img src="https://scontent.fmnl17-2.fna.fbcdn.net/v/t1.15752-9/486533144_1214884303632997_5520626863749638031_n.png?_nc_cat=107&ccb=1-7&_nc_sid=0024fc&_nc_eui2=AeHPY1thk5FWWQBL3-bl5e-aMXCZnJBD4VgxcJmckEPhWNAf0d7unKqt8-cWXqk8I1ntuTBy9vverdJZD00Nzll9&_nc_ohc=XgMaBpel0BkQ7kNvwGC8p-2&_nc_oc=AdkLYOSLUbYTq-Srq5FjegPeU2dA9wLXOwrznrsF5PkRSLOujpTmDpmY50rsleLOVzY&_nc_ad=z-m&_nc_cid=0&_nc_zt=23&_nc_ht=scontent.fmnl17-2.fna&oh=03_Q7cD2QErv6-JNkCVDwto7fAnEWjvCc3HH1g0OkGXS2vbz-Qfww&oe=684225ED" alt="Kalayaan National High School Logo" class="logo-image"> <h1>Kalayaan National High School</h1> <p>Q2JJ+GV9, 1428 Langit Rd, Caloocan, Metro Manila</p> </div> <div class="login-container"> <div class="logo"> <h1>Admin Portal</h1> <p>Secure access to your dashboard</p> </div> <form onsubmit="return login(event)"> <div class="form-group"> <label for="username">Username</label> <input type="text" id="username" placeholder="Enter your username" required /> </div> <div class="form-group"> <label for="password">Password</label> <input type="password" id="password" placeholder="Enter your password" required /> </div> <button type="submit">Sign In</button> <p id="error-message" class="error-message"></p> </form> <div class="footer"> &copy; 2025 Admin Portal. All rights reserved. </div> </div> <script> function login(event) { event.preventDefault(); const username = document.getElementById("username").value; const password = document.getElementById("password").value; const errorElement = document.getElementById("error-message"); if (username === "admin" && password === "knhs25") { errorElement.textContent = ""; window.location.href = "admin.html"; } else { errorElement.textContent = "Invalid credentials. Please try again."; } } </script> </body> </html> // DOM Elements const totalUsersEl = document.getElementById('total-users'); const teacherCountEl = document.getElementById('teacher-count'); const studentCountEl = document.getElementById('student-count'); const parentCountEl = document.getElementById('parent-count'); const usersTableBody = document.querySelector('#users-table tbody'); const userSearchInput = document.getElementById('user-search'); const refreshBtn = document.getElementById('refresh-users'); const addLessonBtn = document.getElementById('add-lesson-btn'); const addQuizBtn = document.getElementById('add-quiz-btn'); const lessonsTableBody = document.getElementById('lessons-table-body'); const quizzesTableBody = document.getElementById('quizzes-table-body'); const tabBtns = document.querySelectorAll('.tab-btn'); const tabContents = document.querySelectorAll('.tab-content'); // Modal Elements const lessonModal = document.getElementById('lesson-modal'); const quizModal = document.getElementById('quiz-modal'); const closeBtns = document.querySelectorAll('.close'); const lessonForm = document.getElementById('lesson-form'); const quizForm = document.getElementById('quiz-form'); const addQuestionBtn = document.getElementById('add-question-btn'); const questionsContainer = document.getElementById('questions-container'); // Initialize the dashboard updateDashboard(); setInterval(updateDashboard, 5000); // Update every 5 seconds // Event listeners refreshBtn.addEventListener('click', updateDashboard); userSearchInput.addEventListener('input', filterUsers); addLessonBtn.addEventListener('click', () => openLessonModal()); addQuizBtn.addEventListener('click', () => openQuizModal()); // Tab switching tabBtns.forEach(btn => { btn.addEventListener('click', () => { const tabId = btn.dataset.tab; switchTab(tabId); }); }); // Add to the existing admin.js document.addEventListener('DOMContentLoaded', () => { // Existing code... // Add logout button functionality const logoutBtn = document.getElementById('logout-btn'); if (logoutBtn) { logoutBtn.addEventListener('click', () => { sessionStorage.clear(); window.location.href = 'login.html'; }); } // Rest of existing JavaScript... }); // Close modals closeBtns.forEach(btn => { btn.addEventListener('click', () => { lessonModal.style.display = 'none'; quizModal.style.display = 'none'; }); }); // Close modals when clicking outside window.addEventListener('click', (e) => { if (e.target === lessonModal) lessonModal.style.display = 'none'; if (e.target === quizModal) quizModal.style.display = 'none'; }); // Lesson form submission lessonForm.addEventListener('submit', handleLessonSubmit); // Quiz form submission quizForm.addEventListener('submit', handleQuizSubmit); // Add question button addQuestionBtn.addEventListener('click', addQuestion); function updateDashboard() { updateUserStats(); populateUsersTable(); populateLessonsTable(); populateQuizzesTable(); } function updateUserStats() { const users = getUsers(); const userCounts = { total: 0, teacher: 0, student: 0, parent: 0 }; for (const username in users) { const user = users[username]; userCounts.total++; if (user.role === 'teacher') userCounts.teacher++; if (user.role === 'student') userCounts.student++; if (user.role === 'parent') userCounts.parent++; } totalUsersEl.textContent = userCounts.total; teacherCountEl.textContent = userCounts.teacher; studentCountEl.textContent = userCounts.student; parentCountEl.textContent = userCounts.parent; } function populateUsersTable() { const users = getUsers(); usersTableBody.innerHTML = ''; for (const username in users) { const user = users[username]; const row = document.createElement('tr'); row.innerHTML = ` <td>${username}</td> <td>${user.role}</td> <td>${user.teacherId || user.studentId || 'N/A'}</td> <td>${user.fullName || 'N/A'}</td> <td> <button class="action-btn edit-btn" data-username="${username}">Edit</button> <button class="action-btn delete-btn" data-username="${username}">Delete</button> </td> `; usersTableBody.appendChild(row); } // Add event listeners to action buttons document.querySelectorAll('.edit-btn').forEach(btn => { btn.addEventListener('click', (e) => { const username = e.target.dataset.username; editUser(username); }); }); document.querySelectorAll('.delete-btn').forEach(btn => { btn.addEventListener('click', (e) => { const username = e.target.dataset.username; deleteUser(username); }); }); } function populateLessonsTable() { const lessons = JSON.parse(localStorage.getItem('createdLessons') || '[]'); lessonsTableBody.innerHTML = ''; if (lessons.length === 0) { lessonsTableBody.innerHTML = '<tr><td colspan="4">No lessons available</td></tr>'; return; } lessons.forEach((lesson, index) => { const row = document.createElement('tr'); const contentPreview = lesson.content.length > 50 ? lesson.content.substring(0, 50) + '...' : lesson.content; row.innerHTML = ` <td>${lesson.title || 'Untitled Lesson'}</td> <td class="content-preview">${contentPreview}</td> <td>${lesson.fileName || 'None'}</td> <td> <button class="action-btn edit-btn" data-index="${index}" data-type="lesson">Edit</button> <button class="action-btn delete-btn" data-index="${index}" data-type="lesson">Delete</button> </td> `; lessonsTableBody.appendChild(row); }); // Add event listeners to lesson action buttons document.querySelectorAll('.edit-btn[data-type="lesson"]').forEach(btn => { btn.addEventListener('click', (e) => { const index = e.target.dataset.index; editLesson(index); }); }); document.querySelectorAll('.delete-btn[data-type="lesson"]').forEach(btn => { btn.addEventListener('click', (e) => { const index = e.target.dataset.index; deleteLesson(index); }); }); } function populateQuizzesTable() { const quizzes = JSON.parse(localStorage.getItem('createdQuizzes') || '[]'); quizzesTableBody.innerHTML = ''; if (quizzes.length === 0) { quizzesTableBody.innerHTML = '<tr><td colspan="4">No quizzes available</td></tr>'; return; } quizzes.forEach((quiz, index) => { const row = document.createElement('tr'); row.innerHTML = ` <td>${quiz.quizTitle || 'Untitled Quiz'}</td> <td>${quiz.quizType || 'N/A'}</td> <td>${quiz.questions ? quiz.questions.length : 0}</td> <td> <button class="action-btn edit-btn" data-index="${index}" data-type="quiz">Edit</button> <button class="action-btn delete-btn" data-index="${index}" data-type="quiz">Delete</button> </td> `; quizzesTableBody.appendChild(row); }); // Add event listeners to quiz action buttons document.querySelectorAll('.edit-btn[data-type="quiz"]').forEach(btn => { btn.addEventListener('click', (e) => { const index = e.target.dataset.index; editQuiz(index); }); }); document.querySelectorAll('.delete-btn[data-type="quiz"]').forEach(btn => { btn.addEventListener('click', (e) => { const index = e.target.dataset.index; deleteQuiz(index); }); }); } function filterUsers() { const searchTerm = userSearchInput.value.toLowerCase(); const rows = usersTableBody.querySelectorAll('tr'); rows.forEach(row => { const username = row.cells[0].textContent.toLowerCase(); const role = row.cells[1].textContent.toLowerCase(); const id = row.cells[2].textContent.toLowerCase(); const name = row.cells[3].textContent.toLowerCase(); if (username.includes(searchTerm) || role.includes(searchTerm) || id.includes(searchTerm) || name.includes(searchTerm)) { row.style.display = ''; } else { row.style.display = 'none'; } }); } function switchTab(tabId) { tabBtns.forEach(btn => btn.classList.remove('active')); tabContents.forEach(content => content.classList.remove('active')); document.querySelector(`.tab-btn[data-tab="${tabId}"]`).classList.add('active'); document.getElementById(tabId).classList.add('active'); } function openLessonModal(lessonIndex = -1) { const modalTitle = document.getElementById('lesson-modal-title'); const editIndexInput = document.getElementById('lesson-edit-index'); const titleInput = document.getElementById('lesson-title'); const contentInput = document.getElementById('lesson-content'); const fileInput = document.getElementById('lesson-file'); const currentFileInfo = document.getElementById('current-file-info'); const currentFileName = document.getElementById('current-file-name'); const removeFileBtn = document.getElementById('remove-file-btn'); // Reset form lessonForm.reset(); currentFileInfo.classList.add('hidden'); fileInput.value = ''; if (lessonIndex >= 0) { // Edit mode const lessons = JSON.parse(localStorage.getItem('createdLessons') || '[]'); const lesson = lessons[lessonIndex]; if (lesson) { modalTitle.textContent = 'Edit Lesson'; editIndexInput.value = lessonIndex; titleInput.value = lesson.title || ''; contentInput.value = lesson.content || ''; if (lesson.fileName) { currentFileName.textContent = lesson.fileName; currentFileInfo.classList.remove('hidden'); } } } else { // Add mode modalTitle.textContent = 'Add New Lesson'; editIndexInput.value = -1; } lessonModal.style.display = 'block'; } function openQuizModal(quizIndex = -1) { const modalTitle = document.getElementById('quiz-modal-title'); const editIndexInput = document.getElementById('quiz-edit-index'); const titleInput = document.getElementById('quiz-title'); const typeInput = document.getElementById('quiz-type'); // Reset form quizForm.reset(); questionsContainer.innerHTML = ''; if (quizIndex >= 0) { // Edit mode const quizzes = JSON.parse(localStorage.getItem('createdQuizzes') || '[]'); const quiz = quizzes[quizIndex]; if (quiz) { modalTitle.textContent = 'Edit Quiz'; editIndexInput.value = quizIndex; titleInput.value = quiz.quizTitle || ''; typeInput.value = quiz.quizType || 'multiple-choice'; // Add existing questions if (quiz.questions && quiz.questions.length > 0) { quiz.questions.forEach((q, qIndex) => { addQuestion({ questionText: q.questionText, correctAnswer: q.correctAnswer, choices: q.choices || [], qIndex: qIndex + 1 }); }); } } } else { // Add mode modalTitle.textContent = 'Add New Quiz'; editIndexInput.value = -1; // Add one empty question by default addQuestion(); } quizModal.style.display = 'block'; } function addQuestion(questionData = null) { const questionCount = questionsContainer.querySelectorAll('.question-container').length + 1; const questionDiv = document.createElement('div'); questionDiv.className = 'question-container'; const qText = questionData ? questionData.questionText : ''; const qAnswer = questionData ? questionData.correctAnswer : ''; const qChoices = questionData ? questionData.choices : ['', '', '', '']; const qIndex = questionData ? questionData.qIndex : questionCount; questionDiv.innerHTML = ` <h4>Question ${qIndex}</h4> <div class="form-group"> <label for="question-${qIndex}-text">Question Text:</label> <input type="text" id="question-${qIndex}-text" value="${qText}" required> </div> <div class="form-group"> <label for="question-${qIndex}-answer">Correct Answer:</label> <input type="text" id="question-${qIndex}-answer" value="${qAnswer}" required> </div> <div class="choices-container" id="choices-${qIndex}" style="display: ${document.getElementById('quiz-type').value === 'multiple-choice' ? 'block' : 'none'}"> <label>Choices:</label> <input type="text" id="question-${qIndex}-choice-1" value="${qChoices[0] || ''}" placeholder="Choice 1"> <input type="text" id="question-${qIndex}-choice-2" value="${qChoices[1] || ''}" placeholder="Choice 2"> <input type="text" id="question-${qIndex}-choice-3" value="${qChoices[2] || ''}" placeholder="Choice 3"> <input type="text" id="question-${qIndex}-choice-4" value="${qChoices[3] || ''}" placeholder="Choice 4"> </div> <button type="button" class="action-btn delete-btn remove-question-btn">Remove Question</button> `; questionsContainer.appendChild(questionDiv); // Add event listener to remove button questionDiv.querySelector('.remove-question-btn').addEventListener('click', () => { questionDiv.remove(); // Re-number remaining questions const questions = questionsContainer.querySelectorAll('.question-container'); questions.forEach((q, index) => { q.querySelector('h4').textContent = `Question ${index + 1}`; }); }); } function handleLessonSubmit(e) { e.preventDefault(); const editIndex = document.getElementById('lesson-edit-index').value; const title = document.getElementById('lesson-title').value; const content = document.getElementById('lesson-content').value; const fileInput = document.getElementById('lesson-file'); const currentFileInfo = document.getElementById('current-file-info'); if (!title || !content) { alert('Please fill in all required fields'); return; } const lessons = JSON.parse(localStorage.getItem('createdLessons') || '[]'); const lessonData = { title, content, fileName: null, fileDataUrl: null }; // Handle file upload if present if (fileInput.files.length > 0) { const file = fileInput.files[0]; const reader = new FileReader(); reader.onload = function(e) { lessonData.fileName = file.name; lessonData.fileDataUrl = e.target.result; saveLesson(lessons, lessonData, editIndex); }; reader.readAsDataURL(file); } else if (currentFileInfo.classList.contains('hidden')) { // No file and no existing file - save without file saveLesson(lessons, lessonData, editIndex); } else { // Keep existing file if not changed const existingLesson = lessons[editIndex]; if (existingLesson) { lessonData.fileName = existingLesson.fileName; lessonData.fileDataUrl = existingLesson.fileDataUrl; } saveLesson(lessons, lessonData, editIndex); } } function saveLesson(lessons, lessonData, editIndex) { if (editIndex >= 0 && editIndex < lessons.length) { // Update existing lesson lessons[editIndex] = lessonData; } else { // Add new lesson lessons.push(lessonData); } localStorage.setItem('createdLessons', JSON.stringify(lessons)); lessonModal.style.display = 'none'; updateDashboard(); alert('Lesson saved successfully!'); } function handleQuizSubmit(e) { e.preventDefault(); const editIndex = document.getElementById('quiz-edit-index').value; const title = document.getElementById('quiz-title').value; const type = document.getElementById('quiz-type').value; const questionContainers = questionsContainer.querySelectorAll('.question-container'); if (!title || questionContainers.length === 0) { alert('Please fill in all required fields and add at least one question'); return; } const questions = []; let allQuestionsValid = true; questionContainers.forEach((container, index) => { const questionText = container.querySelector('input[type="text"]').value; const correctAnswer = container.querySelectorAll('input[type="text"]')[1].value; if (!questionText || !correctAnswer) { allQuestionsValid = false; return; } const question = { questionText, correctAnswer, choices: [] }; if (type === 'multiple-choice') { const choiceInputs = container.querySelectorAll('.choices-container input[type="text"]'); choiceInputs.forEach(input => { if (input.value) { question.choices.push(input.value); } }); if (question.choices.length === 0) { allQuestionsValid = false; return; } } questions.push(question); }); if (!allQuestionsValid) { alert('Please fill in all question fields'); return; } const quizData = { quizTitle: title, quizType: type, questions }; const quizzes = JSON.parse(localStorage.getItem('createdQuizzes') || '[]'); if (editIndex >= 0 && editIndex < quizzes.length) { // Update existing quiz quizzes[editIndex] = quizData; } else { // Add new quiz quizzes.push(quizData); } localStorage.setItem('createdQuizzes', JSON.stringify(quizzes)); quizModal.style.display = 'none'; updateDashboard(); alert('Quiz saved successfully!'); } function editUser(username) { // In a real app, this would open a modal or form to edit the user alert(`Edit functionality for ${username} would open here`); } function deleteUser(username) { if (confirm(`Are you sure you want to delete user ${username}? This cannot be undone.`)) { const users = getUsers(); delete users[username]; saveUsers(users); updateDashboard(); alert(`User ${username} has been deleted.`); } } function editLesson(index) { openLessonModal(index); } function deleteLesson(index) { if (confirm('Are you sure you want to delete this lesson? This cannot be undone.')) { const lessons = JSON.parse(localStorage.getItem('createdLessons') || '[]'); lessons.splice(index, 1); localStorage.setItem('createdLessons', JSON.stringify(lessons)); updateDashboard(); alert('Lesson deleted successfully!'); } } function editQuiz(index) { openQuizModal(index); } function deleteQuiz(index) { if (confirm('Are you sure you want to delete this quiz? This cannot be undone.')) { const quizzes = JSON.parse(localStorage.getItem('createdQuizzes') || '[]'); quizzes.splice(index, 1); localStorage.setItem('createdQuizzes', JSON.stringify(quizzes)); updateDashboard(); alert('Quiz deleted successfully!'); } }
Updated files
v1
When the admin dashboard creates an assignment, he needs to be able to select the grade & section, not the student. For example, the section I chose is Grade 8 - Section 1. When will the assignment I created go there? In the admin dashboard, only they need to be able to see the assignment I created. I need the full code for it and it all needs to function. <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <title>Admin Dashboard - KNHS</title> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet"> <style> :root { --primary: #4f46e5; --primary-hover: #4338ca; --muted: #6b7280; --card-bg: rgba(255,255,255,0.9); } body { font-family: 'Inter', sans-serif; margin: 0; padding: 24px; background: linear-gradient(180deg,#eef2ff 0%, #ffffff 100%); } header { display: flex; justify-content: space-between; align-items: center; gap: 16px; margin-bottom: 18px; } header h1 { margin: 0; color: #0f172a; } .btn { background: var(--primary); color: white; border: none; padding: 10px 14px; border-radius: 8px; cursor: pointer; font-weight: 600; } .btn.secondary { background: white; color: var(--primary); border: 1px solid rgba(79,70,229,0.15); } .layout { display: grid; grid-template-columns: 320px 1fr; gap: 20px; } .sidebar { background: var(--card-bg); padding: 16px; border-radius: 12px; box-shadow: 0 6px 18px rgba(2,6,23,0.06); } .content { background: var(--card-bg); padding: 18px; border-radius: 12px; box-shadow: 0 6px 18px rgba(2,6,23,0.06); } .stat { display: flex; justify-content: space-between; margin-bottom: 8px; } .nav { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; } .tab-btn { padding: 8px 10px; background: transparent; border-radius: 8px; cursor: pointer; border: 1px solid transparent; } .tab-btn.active { background: var(--primary); color: white; } table { width: 100%; border-collapse: collapse; margin-top: 10px; } th, td { text-align: left; padding: 8px; border-bottom: 1px solid rgba(0,0,0,0.06); font-size: 14px; } .actions { display:flex; gap:6px; } .modal { display:none; position: fixed; left:0; top:0; right:0; bottom:0; background: rgba(0,0,0,0.4); align-items:center; justify-content:center; z-index:50; } .modal .panel { background: white; padding:16px; border-radius:10px; width: 720px; max-width:95%; max-height:90vh; overflow:auto; } .close { float:right; border:none; background:transparent; font-size:18px; cursor:pointer; } input, textarea, select { width:100%; padding:8px; margin:6px 0 12px; border:1px solid #e6e6f0; border-radius:6px; box-sizing:border-box; } .hidden { display:none; } .small { font-size:13px; color:var(--muted); } </style> </head> <body> <header> <div> <h1>Admin Dashboard — Kalayaan NHS</h1> <div class="small">Manage users, lessons, quizzes, assignments & grades</div> </div> <div style="display:flex;gap:8px;align-items:center"> <button id="create-assignment-btn" class="btn">Create Assignment</button> <button id="manage-grades-btn" class="btn secondary">Manage Scores & Grades</button> <button id="logout-btn" class="btn">Logout</button> </div> </header> <div class="layout"> <aside class="sidebar"> <div class="stat"><div>Total Users</div><div id="total-users">0</div></div> <div class="stat"><div>Teachers</div><div id="teacher-count">0</div></div> <div class="stat"><div>Students</div><div id="student-count">0</div></div> <div class="stat"><div>Parents</div><div id="parent-count">0</div></div> <hr /> <div style="margin-top:12px"> <input type="text" id="user-search" placeholder="Search users..." /> <button id="refresh-users" class="btn" style="width:100%;margin-top:8px">Refresh</button> </div> </aside> <main class="content"> <div class="nav" id="tabs"> <button class="tab-btn active" data-tab="users-tab">Users</button> <button class="tab-btn" data-tab="lessons-tab">Lessons</button> <button class="tab-btn" data-tab="quizzes-tab">Quizzes</button> <button class="tab-btn" data-tab="assignments-tab">Assignments</button> </div> <section id="users-tab" class="tab-content active"> <h3>Users</h3> <table id="users-table"> <thead> <tr><th>Username</th><th>Role</th><th>ID</th><th>Full Name</th><th>Actions</th></tr> </thead> <tbody></tbody> </table> </section> <section id="lessons-tab" class="tab-content hidden"> <h3>Lessons</h3> <button id="add-lesson-btn" class="btn">Add Lesson</button> <table> <thead><tr><th>Title</th><th>Preview</th><th>File</th><th>Actions</th></tr></thead> <tbody id="lessons-table-body"></tbody> </table> </section> <section id="quizzes-tab" class="tab-content hidden"> <h3>Quizzes</h3> <button id="add-quiz-btn" class="btn">Add Quiz</button> <table> <thead><tr><th>Title</th><th>Type</th><th>#Questions</th><th>Actions</th></tr></thead> <tbody id="quizzes-table-body"></tbody> </table> </section> <section id="assignments-tab" class="tab-content hidden"> <h3>Assignments</h3> <table> <thead><tr><th>Title</th><th>Assigned To</th><th>Due Date</th><th>Actions</th></tr></thead> <tbody id="assignments-table-body"></tbody> </table> </section> </main> </div> <!-- Lesson Modal --> <div id="lesson-modal" class="modal"> <div class="panel"> <button class="close" id="close-lesson-modal">&times;</button> <h3 id="lesson-modal-title">Add New Lesson</h3> <form id="lesson-form"> <input type="hidden" id="lesson-edit-index" value="-1"> <label>Lesson Title</label> <input id="lesson-title" required /> <label>Content</label> <textarea id="lesson-content" rows="6" required></textarea> <label>Attach File (optional)</label> <input id="lesson-file" type="file" /> <div id="current-file-info" class="hidden">Current File: <span id="current-file-name"></span> <button id="remove-file-btn" type="button">Remove</button></div> <button class="btn" type="submit">Save Lesson</button> </form> </div> </div> <!-- Quiz Modal --> <div id="quiz-modal" class="modal"> <div class="panel"> <button class="close" id="close-quiz-modal">&times;</button> <h3 id="quiz-modal-title">Add New Quiz</h3> <form id="quiz-form"> <input type="hidden" id="quiz-edit-index" value="-1"> <label>Quiz Title</label> <input id="quiz-title" required /> <label>Type</label> <select id="quiz-type"> <option value="multiple-choice">Multiple Choice</option> <option value="short-answer">Short Answer</option> </select> <div id="questions-container"></div> <button id="add-question-btn" type="button" class="btn secondary">Add Question</button> <div style="margin-top:12px"> <button type="submit" class="btn">Save Quiz</button> </div> </form> </div> </div> <!-- Assignment Modal --> <div id="assignment-modal" class="modal"> <div class="panel"> <button class="close" id="close-assignment-modal">&times;</button> <h3 id="assignment-modal-title">Create Assignment</h3> <form id="assignment-form"> <input type="hidden" id="assignment-edit-id" value=""> <label>Title</label> <input id="assignment-title" required /> <label>Description</label> <textarea id="assignment-desc" rows="4"></textarea> <label>Assign To</label> <select id="assignment-assigned-to"> <option value="all">All Students</option> </select> <label>Due Date</label> <input id="assignment-due" type="date" required /> <button class="btn" type="submit">Save Assignment</button> </form> </div> </div> <!-- Manage Grades Modal --> <div id="grades-modal" class="modal"> <div class="panel"> <button class="close" id="close-grades-modal">&times;</button> <h3>Manage Scores & Grades</h3> <div> <label>Select Assignment</label> <select id="grades-assignment-select"></select> </div> <div style="margin-top:12px"> <table id="grades-table"> <thead><tr><th>Student</th><th>Student ID</th><th>Grade</th><th>Actions</th></tr></thead> <tbody></tbody> </table> <div style="margin-top:10px"> <button id="save-grades-btn" class="btn">Save Grades</button> </div> </div> </div> </div> <script src="admin.js"></script> </body> </html> // Admin dashboard script: users, lessons, quizzes, assignments & grades // Utility helpers function getUsers() { return JSON.parse(localStorage.getItem('users') || '{}'); } function saveUsers(users) { localStorage.setItem('users', JSON.stringify(users)); } function ensureDemoData() { // Ensure demo users already created by login page, but double-check const users = getUsers(); if (!users.admin) { users.admin = { username: 'admin', password: 'knhs25', role: 'admin', fullName: 'Administrator' }; } if (!users.student1) { users.student1 = { username: 'student1', password: 'studentpass', role: 'student', fullName: 'Juan Dela Cruz', studentId: 'S-001' }; } if (!users.student2) { users.student2 = { username: 'student2', password: 'studentpass', role: 'student', fullName: 'Maria Santos', studentId: 'S-002' }; } if (!users.teacher1) { users.teacher1 = { username: 'teacher1', password: 'teacherpass', role: 'teacher', fullName: 'Mrs. Reyes', teacherId: 'T-01' }; } saveUsers(users); // Ensure arrays exist if (!localStorage.getItem('createdLessons')) localStorage.setItem('createdLessons', JSON.stringify([])); if (!localStorage.getItem('createdQuizzes')) localStorage.setItem('createdQuizzes', JSON.stringify([])); if (!localStorage.getItem('assignments')) localStorage.setItem('assignments', JSON.stringify([])); if (!localStorage.getItem('grades')) localStorage.setItem('grades', JSON.stringify({})); } // DOM Elements const totalUsersEl = document.getElementById('total-users'); const teacherCountEl = document.getElementById('teacher-count'); const studentCountEl = document.getElementById('student-count'); const parentCountEl = document.getElementById('parent-count'); const usersTableBody = document.querySelector('#users-table tbody'); const userSearchInput = document.getElementById('user-search'); const refreshBtn = document.getElementById('refresh-users'); const addLessonBtn = document.getElementById('add-lesson-btn'); const addQuizBtn = document.getElementById('add-quiz-btn'); const lessonsTableBody = document.getElementById('lessons-table-body'); const quizzesTableBody = document.getElementById('quizzes-table-body'); const tabBtns = document.querySelectorAll('.tab-btn'); const tabContents = document.querySelectorAll('.tab-content'); // Assignment and Grades elements const createAssignmentBtn = document.getElementById('create-assignment-btn'); const manageGradesBtn = document.getElementById('manage-grades-btn'); const assignmentsTableBody = document.getElementById('assignments-table-body'); const assignmentModal = document.getElementById('assignment-modal'); const closeAssignmentModalBtn = document.getElementById('close-assignment-modal'); const assignmentForm = document.getElementById('assignment-form'); const assignmentAssignedToSel = document.getElementById('assignment-assigned-to'); const gradesModal = document.getElementById('grades-modal'); const closeGradesModalBtn = document.getElementById('close-grades-modal'); const gradesAssignmentSelect = document.getElementById('grades-assignment-select'); const gradesTableBody = document.querySelector('#grades-table tbody'); const saveGradesBtn = document.getElementById('save-grades-btn'); // Lesson & Quiz modals existing const lessonModal = document.getElementById('lesson-modal'); const quizModal = document.getElementById('quiz-modal'); const closeLessonModalBtn = document.getElementById('close-lesson-modal'); const closeQuizModalBtn = document.getElementById('close-quiz-modal'); const lessonForm = document.getElementById('lesson-form'); const quizForm = document.getElementById('quiz-form'); const addQuestionBtn = document.getElementById('add-question-btn'); const questionsContainer = document.getElementById('questions-container'); // Close buttons for lesson & quiz document.getElementById('close-lesson-modal').addEventListener('click', () => lessonModal.style.display = 'none'); document.getElementById('close-quiz-modal').addEventListener('click', () => quizModal.style.display = 'none'); // Build initial data and UI ensureDemoData(); updateDashboard(); setInterval(updateDashboard, 5000); // Event listeners refreshBtn.addEventListener('click', updateDashboard); userSearchInput.addEventListener('input', filterUsers); addLessonBtn && addLessonBtn.addEventListener('click', () => openLessonModal()); addQuizBtn && addQuizBtn.addEventListener('click', () => openQuizModal()); // Tabs tabBtns.forEach(btn => { btn.addEventListener('click', () => { const tabId = btn.dataset.tab; switchTab(tabId); }); }); // Logout const logoutBtn = document.getElementById('logout-btn'); if (logoutBtn) { logoutBtn.addEventListener('click', () => { sessionStorage.clear(); window.location.href = 'login.html'; }); } // Lesson & Quiz modal behavior window.addEventListener('click', (e) => { if (e.target === lessonModal) lessonModal.style.display = 'none'; if (e.target === quizModal) quizModal.style.display = 'none'; if (e.target === assignmentModal) assignmentModal.style.display = 'none'; if (e.target === gradesModal) gradesModal.style.display = 'none'; }); // Lesson & Quiz forms lessonForm.addEventListener('submit', handleLessonSubmit); quizForm.addEventListener('submit', handleQuizSubmit); addQuestionBtn.addEventListener('click', addQuestion); // Assignment buttons createAssignmentBtn.addEventListener('click', openAssignmentModal); closeAssignmentModalBtn.addEventListener('click', () => assignmentModal.style.display = 'none'); assignmentForm.addEventListener('submit', handleAssignmentSubmit); // Grades buttons manageGradesBtn.addEventListener('click', openGradesModal); closeGradesModalBtn.addEventListener('click', () => gradesModal.style.display = 'none'); gradesAssignmentSelect.addEventListener('change', populateGradesTable); saveGradesBtn.addEventListener('click', saveGrades); // Functions for dashboard function updateDashboard() { updateUserStats(); populateUsersTable(); populateLessonsTable(); populateQuizzesTable(); populateAssignmentsTable(); populateAssignmentSelectors(); } function updateUserStats() { const users = getUsers(); const counts = { total: 0, teacher: 0, student: 0, parent: 0 }; for (const k in users) { counts.total++; if (users[k].role === 'teacher') counts.teacher++; if (users[k].role === 'student') counts.student++; if (users[k].role === 'parent') counts.parent++; } totalUsersEl.textContent = counts.total; teacherCountEl.textContent = counts.teacher; studentCountEl.textContent = counts.student; parentCountEl.textContent = counts.parent; } function populateUsersTable() { const users = getUsers(); usersTableBody.innerHTML = ''; for (const username in users) { const user = users[username]; const row = document.createElement('tr'); row.innerHTML = ` <td>${username}</td> <td>${user.role}</td> <td>${user.teacherId || user.studentId || 'N/A'}</td> <td>${user.fullName || 'N/A'}</td> <td class="actions"> <button class="btn secondary edit-user" data-username="${username}">Edit</button> <button class="btn" data-username="${username}" style="background:#ef4444">Delete</button> </td> `; usersTableBody.appendChild(row); } document.querySelectorAll('#users-table .edit-user').forEach(btn => { btn.addEventListener('click', (e) => { const username = e.target.dataset.username; editUser(username); }); }); document.querySelectorAll('#users-table button[style]').forEach(btn => { btn.addEventListener('click', (e) => { const username = e.target.dataset.username; if (confirm(`Delete user ${username}?`)) { const users = getUsers(); delete users[username]; saveUsers(users); updateDashboard(); alert('User deleted'); } }); }); } function filterUsers() { const searchTerm = userSearchInput.value.toLowerCase(); const rows = usersTableBody.querySelectorAll('tr'); rows.forEach(row => { const username = row.cells[0].textContent.toLowerCase(); const role = row.cells[1].textContent.toLowerCase(); const id = row.cells[2].textContent.toLowerCase(); const name = row.cells[3].textContent.toLowerCase(); if (username.includes(searchTerm) || role.includes(searchTerm) || id.includes(searchTerm) || name.includes(searchTerm)) { row.style.display = ''; } else row.style.display = 'none'; }); } function switchTab(tabId) { tabBtns.forEach(b => b.classList.remove('active')); tabContents.forEach(c => c.classList.add('hidden')); document.querySelector(`.tab-btn[data-tab="${tabId}"]`).classList.add('active'); document.getElementById(tabId).classList.remove('hidden'); } // Lessons function populateLessonsTable() { const lessons = JSON.parse(localStorage.getItem('createdLessons') || '[]'); lessonsTableBody.innerHTML = ''; if (lessons.length === 0) { lessonsTableBody.innerHTML = '<tr><td colspan="4">No lessons available</td></tr>'; return; } lessons.forEach((lesson, i) => { const contentPreview = lesson.content ? (lesson.content.length > 50 ? lesson.content.substring(0,50) + '...' : lesson.content) : 'N/A'; const row = document.createElement('tr'); row.innerHTML = `<td>${lesson.title || 'Untitled'}</td><td>${contentPreview}</td><td>${lesson.fileName || 'None'}</td><td class="actions"><button class="btn secondary edit-lesson" data-index="${i}">Edit</button><button class="btn" style="background:#ef4444" data-index="${i}">Delete</button></td>`; lessonsTableBody.appendChild(row); }); document.querySelectorAll('.edit-lesson').forEach(btn => { btn.addEventListener('click', (e) => editLesson(e.target.dataset.index)); }); document.querySelectorAll('#lessons-table-body button[style]').forEach(btn => { btn.addEventListener('click', (e) => { const idx = e.target.dataset.index; if (confirm('Delete this lesson?')) { const lessons = JSON.parse(localStorage.getItem('createdLessons') || '[]'); lessons.splice(idx, 1); localStorage.setItem('createdLessons', JSON.stringify(lessons)); updateDashboard(); } }); }); } function openLessonModal(index = -1) { const modalTitle = document.getElementById('lesson-modal-title'); const editIndexInput = document.getElementById('lesson-edit-index'); const titleInput = document.getElementById('lesson-title'); const contentInput = document.getElementById('lesson-content'); const fileInput = document.getElementById('lesson-file'); const currentFileInfo = document.getElementById('current-file-info'); const currentFileName = document.getElementById('current-file-name'); lessonForm.reset(); currentFileInfo.classList.add('hidden'); fileInput.value = ''; if (index >= 0) { const lessons = JSON.parse(localStorage.getItem('createdLessons') || '[]'); const lesson = lessons[index]; if (lesson) { modalTitle.textContent = 'Edit Lesson'; editIndexInput.value = index; titleInput.value = lesson.title || ''; contentInput.value = lesson.content || ''; if (lesson.fileName) { currentFileName.textContent = lesson.fileName; currentFileInfo.classList.remove('hidden'); } } } else { modalTitle.textContent = 'Add New Lesson'; editIndexInput.value = -1; } lessonModal.style.display = 'flex'; } function handleLessonSubmit(e) { e.preventDefault(); const editIndex = Number(document.getElementById('lesson-edit-index').value); const title = document.getElementById('lesson-title').value; const content = document.getElementById('lesson-content').value; const fileInput = document.getElementById('lesson-file'); const lessons = JSON.parse(localStorage.getItem('createdLessons') || '[]'); const lessonData = { title, content, fileName: null, fileDataUrl: null }; if (fileInput.files.length > 0) { const file = fileInput.files[0]; const reader = new FileReader(); reader.onload = function(ev) { lessonData.fileName = file.name; lessonData.fileDataUrl = ev.target.result; saveLesson(lessons, lessonData, editIndex); }; reader.readAsDataURL(file); } else { // keep existing file if editing if (editIndex >= 0 && lessons[editIndex]) { lessonData.fileName = lessons[editIndex].fileName; lessonData.fileDataUrl = lessons[editIndex].fileDataUrl; } saveLesson(lessons, lessonData, editIndex); } } function saveLesson(lessons, lessonData, editIndex) { if (editIndex >= 0 && editIndex < lessons.length) lessons[editIndex] = lessonData; else lessons.push(lessonData); localStorage.setItem('createdLessons', JSON.stringify(lessons)); lessonModal.style.display = 'none'; updateDashboard(); alert('Lesson saved!'); } function editLesson(index) { openLessonModal(Number(index)); } // Quizzes function populateQuizzesTable() { const quizzes = JSON.parse(localStorage.getItem('createdQuizzes') || '[]'); quizzesTableBody.innerHTML = ''; if (quizzes.length === 0) { quizzesTableBody.innerHTML = '<tr><td colspan="4">No quizzes available</td></tr>'; return; } quizzes.forEach((quiz, i) => { const row = document.createElement('tr'); row.innerHTML = `<td>${quiz.quizTitle || 'Untitled'}</td><td>${quiz.quizType || 'N/A'}</td><td>${quiz.questions ? quiz.questions.length : 0}</td><td class="actions"><button class="btn secondary edit-quiz" data-index="${i}">Edit</button><button class="btn" style="background:#ef4444" data-index="${i}">Delete</button></td>`; quizzesTableBody.appendChild(row); }); document.querySelectorAll('.edit-quiz').forEach(btn => { btn.addEventListener('click', (e) => openQuizModal(Number(e.target.dataset.index)))}); document.querySelectorAll('#quizzes-table-body button[style]').forEach(btn => { btn.addEventListener('click', (e) => { const idx = e.target.dataset.index; if (confirm('Delete this quiz?')) { const quizzes = JSON.parse(localStorage.getItem('createdQuizzes') || '[]'); quizzes.splice(idx,1); localStorage.setItem('createdQuizzes', JSON.stringify(quizzes)); updateDashboard(); } }); }); } function openQuizModal(quizIndex = -1) { const modalTitle = document.getElementById('quiz-modal-title'); const editIndexInput = document.getElementById('quiz-edit-index'); const titleInput = document.getElementById('quiz-title'); const typeInput = document.getElementById('quiz-type'); quizForm.reset(); questionsContainer.innerHTML = ''; if (quizIndex >= 0) { const quizzes = JSON.parse(localStorage.getItem('createdQuizzes') || '[]'); const quiz = quizzes[quizIndex]; if (quiz) { modalTitle.textContent = 'Edit Quiz'; editIndexInput.value = quizIndex; titleInput.value = quiz.quizTitle || ''; typeInput.value = quiz.quizType || 'multiple-choice'; if (quiz.questions && quiz.questions.length) { quiz.questions.forEach((q, idx) => { addQuestion({ questionText: q.questionText, correctAnswer: q.correctAnswer, choices: q.choices || [], qIndex: idx + 1 }); }); } } } else { modalTitle.textContent = 'Add New Quiz'; editIndexInput.value = -1; addQuestion(); } quizModal.style.display = 'flex'; } function addQuestion(questionData = null) { const questionCount = questionsContainer.querySelectorAll('.question-container').length + 1; const qText = questionData ? questionData.questionText : ''; const qAnswer = questionData ? questionData.correctAnswer : ''; const qChoices = questionData ? questionData.choices : ['', '', '', '']; const qIndex = questionData ? questionData.qIndex : questionCount; const questionDiv = document.createElement('div'); questionDiv.className = 'question-container'; questionDiv.innerHTML = ` <h4>Question ${qIndex}</h4> <div class="form-group"> <label>Question Text:</label> <input type="text" class="q-text" value="${qText}" required> </div> <div class="form-group"> <label>Correct Answer:</label> <input type="text" class="q-answer" value="${qAnswer}" required> </div> <div class="choices-container"> <label>Choices (for multiple choice)</label> <input type="text" class="q-choice" value="${qChoices[0] || ''}" placeholder="Choice 1"> <input type="text" class="q-choice" value="${qChoices[1] || ''}" placeholder="Choice 2"> <input type="text" class="q-choice" value="${qChoices[2] || ''}" placeholder="Choice 3"> <input type="text" class="q-choice" value="${qChoices[3] || ''}" placeholder="Choice 4"> </div> <button type="button" class="btn" style="background:#ef4444" data-action="remove-question">Remove Question</button> `; questionsContainer.appendChild(questionDiv); questionDiv.querySelector('[data-action="remove-question"]').addEventListener('click', () => { questionDiv.remove(); const rem = questionsContainer.querySelectorAll('.question-container'); rem.forEach((r, idx) => r.querySelector('h4').textContent = `Question ${idx + 1}`); }); } function handleQuizSubmit(e) { e.preventDefault(); const editIndex = Number(document.getElementById('quiz-edit-index').value); const title = document.getElementById('quiz-title').value; const type = document.getElementById('quiz-type').value; const containers = questionsContainer.querySelectorAll('.question-container'); if (!title || containers.length === 0) return alert('Please provide title and at least one question.'); const questions = []; let valid = true; containers.forEach(c => { const qText = c.querySelector('.q-text').value.trim(); const qAnswer = c.querySelector('.q-answer').value.trim(); if (!qText || !qAnswer) valid = false; const q = { questionText: qText, correctAnswer: qAnswer, choices: [] }; if (type === 'multiple-choice') { c.querySelectorAll('.q-choice').forEach(ci => { if (ci.value.trim()) q.choices.push(ci.value.trim()); }); if (q.choices.length === 0) valid = false; } questions.push(q); }); if (!valid) return alert('Please fill all question fields.'); const quizzes = JSON.parse(localStorage.getItem('createdQuizzes') || '[]'); const quizData = { quizTitle: title, quizType: type, questions }; if (editIndex >= 0 && editIndex < quizzes.length) quizzes[editIndex] = quizData; else quizzes.push(quizData); localStorage.setItem('createdQuizzes', JSON.stringify(quizzes)); quizModal.style.display = 'none'; updateDashboard(); alert('Quiz saved!'); } // Assignments function openAssignmentModal(editId = '') { const assignTo = document.getElementById('assignment-assigned-to'); assignTo.innerHTML = '<option value="all">All Students</option>'; const users = getUsers(); for (const u in users) { if (users[u].role === 'student') { const opt = document.createElement('option'); opt.value = u; opt.textContent = `${users[u].fullName || u} (${users[u].studentId || u})`; assignTo.appendChild(opt); } } document.getElementById('assignment-edit-id').value = editId || ''; if (editId) { const assignments = JSON.parse(localStorage.getItem('assignments') || '[]'); const a = assignments.find(x => x.id === editId); if (a) { document.getElementById('assignment-title').value = a.title; document.getElementById('assignment-desc').value = a.description; document.getElementById('assignment-due').value = a.dueDate; document.getElementById('assignment-assigned-to').value = a.assignedTo || 'all'; } } else { assignmentForm.reset(); } assignmentModal.style.display = 'flex'; } function handleAssignmentSubmit(e) { e.preventDefault(); const id = document.getElementById('assignment-edit-id').value || String(Date.now()); const title = document.getElementById('assignment-title').value.trim(); const description = document.getElementById('assignment-desc').value.trim(); const assignedTo = document.getElementById('assignment-assigned-to').value; const dueDate = document.getElementById('assignment-due').value; if (!title || !dueDate) return alert('Please provide title and due date.'); const assignments = JSON.parse(localStorage.getItem('assignments') || '[]'); const existingIndex = assignments.findIndex(a => a.id === id); const data = { id, title, description, assignedTo, dueDate, createdAt: new Date().toISOString() }; if (existingIndex >= 0) assignments[existingIndex] = data; else assignments.push(data); localStorage.setItem('assignments', JSON.stringify(assignments)); assignmentModal.style.display = 'none'; updateDashboard(); alert('Assignment saved!'); } function populateAssignmentsTable() { const assignments = JSON.parse(localStorage.getItem('assignments') || '[]'); assignmentsTableBody.innerHTML = ''; if (assignments.length === 0) { assignmentsTableBody.innerHTML = '<tr><td colspan="4">No assignments</td></tr>'; return; } const users = getUsers(); assignments.forEach((a, i) => { const assignedToLabel = (a.assignedTo === 'all') ? 'All Students' : (users[a.assignedTo] ? users[a.assignedTo].fullName : a.assignedTo); const row = document.createElement('tr'); row.innerHTML = `<td>${a.title}</td><td>${assignedToLabel}</td><td>${a.dueDate}</td><td class="actions"><button class="btn secondary edit-assignment" data-id="${a.id}">Edit</button><button class="btn" style="background:#ef4444" data-id="${a.id}">Delete</button></td>`; assignmentsTableBody.appendChild(row); }); document.querySelectorAll('.edit-assignment').forEach(btn => { btn.addEventListener('click', (e) => openAssignmentModal(e.target.dataset.id)); }); document.querySelectorAll('#assignments-table-body button[style]').forEach(btn => { btn.addEventListener('click', (e) => { const id = e.target.dataset.id; if (confirm('Delete this assignment?')) { const assignments = JSON.parse(localStorage.getItem('assignments') || '[]'); const idx = assignments.findIndex(x => x.id === id); if (idx >= 0) assignments.splice(idx,1); localStorage.setItem('assignments', JSON.stringify(assignments)); updateDashboard(); } }); }); } function populateAssignmentSelectors() { const assignments = JSON.parse(localStorage.getItem('assignments') || '[]'); gradesAssignmentSelect.innerHTML = ''; if (assignments.length === 0) { const opt = document.createElement('option'); opt.value = ''; opt.textContent = 'No assignments'; gradesAssignmentSelect.appendChild(opt); return; } assignments.forEach(a => { const opt = document.createElement('option'); opt.value = a.id; opt.textContent = `${a.title} — due ${a.dueDate}`; gradesAssignmentSelect.appendChild(opt); }); } // Grades management function openGradesModal() { populateAssignmentSelectors(); gradesModal.style.display = 'flex'; // Auto-select first assignment if any if (gradesAssignmentSelect.options.length > 0) { gradesAssignmentSelect.selectedIndex = 0; populateGradesTable(); } } function populateGradesTable() { const assignmentId = gradesAssignmentSelect.value; gradesTableBody.innerHTML = ''; if (!assignmentId) return; const users = getUsers(); const assignments = JSON.parse(localStorage.getItem('assignments') || '[]'); const assignment = assignments.find(a => a.id === assignmentId); if (!assignment) return; const students = []; for (const u in users) if (users[u].role === 'student') students.push(users[u]); // filter if assigned to specific student const filtered = (assignment.assignedTo === 'all') ? students : students.filter(s => s.username === assignment.assignedTo || s.username === assignment.assignedTo); const grades = JSON.parse(localStorage.getItem('grades') || '{}'); filtered.forEach(s => { const tr = document.createElement('tr'); const existing = (grades[s.username] && grades[s.username][assignmentId] !== undefined) ? grades[s.username][assignmentId] : ''; tr.innerHTML = `<td>${s.fullName || s.username}</td><td>${s.studentId || ''}</td><td><input type="text" data-student="${s.username}" class="grade-input" value="${existing}"></td><td><button class="btn secondary clear-grade" data-student="${s.username}">Clear</button></td>`; gradesTableBody.appendChild(tr); }); document.querySelectorAll('.clear-grade').forEach(b => { b.addEventListener('click', (e) => { const stu = e.target.dataset.student; const input = document.querySelector(`.grade-input[data-student="${stu}"]`); if (input) input.value = ''; }); }); } function saveGrades() { const assignmentId = gradesAssignmentSelect.value; if (!assignmentId) return alert('Select assignment first.'); const inputs = document.querySelectorAll('.grade-input'); const gradesData = JSON.parse(localStorage.getItem('grades') || '{}'); inputs.forEach(inp => { const student = inp.dataset.student; const val = inp.value.trim(); if (!gradesData[student]) gradesData[student] = {}; if (val === '') delete gradesData[student][assignmentId]; else gradesData[student][assignmentId] = val; }); localStorage.setItem('grades', JSON.stringify(gradesData)); alert('Grades saved.'); gradesModal.style.display = 'none'; } // Simple edit user placeholder function editUser(username) { alert(`Edit user: ${username} — (not implemented full form in this prototype)`); }
Updated files
v2
Add this html here <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <title>Student Dashboard - KNHS</title> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap" rel="stylesheet"> <style> body { font-family: 'Inter', sans-serif; margin:20px; background:#f8fafc; } header { display:flex; justify-content:space-between; align-items:center; } .card { background:white; padding:16px; border-radius:10px; box-shadow:0 6px 18px rgba(2,6,23,0.06); margin-top:12px; } h2 { margin:0 0 8px 0; } table { width:100%; border-collapse:collapse; margin-top:8px; } th,td { text-align:left; padding:8px; border-bottom:1px solid #f1f5f9; } .btn { background:#4f46e5; color:white; padding:8px 10px; border-radius:8px; border:none; cursor:pointer; } .small { color:#64748b; font-size:13px; } </style> </head> <body> <header> <div> <h2>Student Dashboard</h2> <div id="student-name" class="small"></div> <div id="student-grade-section" class="small"></div> </div> <div> <button id="logout" class="btn">Logout</button> </div> </header> <div class="card"> <h3>Assignments</h3> <table id="student-assignments-table"> <thead><tr><th>Title</th><th>Due</th><th>Status</th><th>Grade</th><th>Action</th></tr></thead> <tbody></tbody> </table> </div> <script src="student.js"></script> </body> </html> to this html, they need to be one html. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Student Dashboard</title> <link rel="stylesheet" href="student.css"> <link rel="stylesheet" href="modal.css"> <link rel="stylesheet" href="navbar.css"> <style> .header-container { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .notification-container { position: relative; } .notification-btn { background-color: #f39c12; color: white; border: none; border-radius: 5px; padding: 10px 15px; cursor: pointer; font-size: 16px; } .notification-btn:hover { background-color: #e67e22; } .notification-dropdown { position: absolute; top: 50px; right: 0; width: 300px; background-color: white; border: 1px solid #ccc; border-radius: 5px; padding: 10px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); display: none; z-index: 1000; max-height: 400px; overflow-y: auto; } .notification-dropdown.visible { display: block; } .notification-item { padding: 8px 0; border-bottom: 1px solid #eee; } .notification-item:last-child { border-bottom: none; } .notification-item.unread { background-color: #f8f9fa; } .notification-badge { position: absolute; top: -8px; right: -8px; background-color: #e74c3c; color: white; border-radius: 50%; width: 20px; height: 20px; font-size: 12px; display: flex; align-items: center; justify-content: center; } </style> </head> <body> <div class="container"> <div class="header-container"> <h1>Student Dashboard</h1> <div class="notification-container"> <button id="notificationBtn" class="notification-btn">Notifications</button> <div id="notificationBadge" class="notification-badge" style="display: none;">0</div> <div id="notificationDropdown" class="notification-dropdown"> <p>No new notifications.</p> </div> </div> </div> <!-- Quiz Completion Status Message --> <div id="quiz-completion-status" class="completion-notice hidden"> <p>Please complete all available quizzes to view your performance analytics.</p> </div> <!-- Display Created Lessons --> <section id="lessons-section"> <h2>Available Lessons</h2> <div id="createdLessons"> <p>Loading lessons...</p> </div> </section> <!-- Display Created Quizzes --> <section id="quizzes-section"> <h2>Available Quizzes</h2> <div id="createdQuizzes"> <p>Loading quizzes...</p> </div> </section> <!-- Display Created Assignments --> <section id="assignments-section"> <h2>Available Assignments</h2> <div id="createdAssignments"> <p>Loading assignments...</p> </div> </section> <!-- Performance Analytics Button --> <button id="analyticsBtn" class="analytics-btn" enabled>View Performance & Analytics</button> <!-- Performance Analytics Modal --> <div id="analyticsModal" class="modal"> <div class="modal-content"> <h2>Performance & Analytics</h2> <div class="analytics-section"> <h3>Activity</h3> <p><strong>Last Accessed:</strong> <span id="lastAccessed">N/A</span></p> </div> <div class="analytics-section"> <h3>Lesson Progress</h3> <ul id="lessonProgressList"> <li>Loading lesson status...</li> </ul> </div> <div class="analytics-section"> <h3>Quiz Scores</h3> <ul id="quizScoresList"> <li>No quizzes taken yet.</li> </ul> </div> <div class="analytics-section"> <h3>Assignment Status</h3> <ul id="assignmentStatusList"> <li>No assignments yet.</li> </ul> </div> <div class="analytics-section"> <h3>Overall Grade</h3> <p><strong id="overallGrade">N/A</strong></p> </div> <div class="modal-navigation"> <button id="modalDashboardBtn" class="modal-nav-btn dashboard">Back to Dashboard</button> <button id="modalHomeBtn" class="modal-nav-btn home">Homepage</button> <button id="modalLogoutBtn" class="modal-nav-btn logout">Logout</button> </div> </div> </div> </div> <script src="login.js"></script> <script src="student.js"></script> </body> </html>
Updated files
v3