1 Gemnew
1 Gemnew
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>College Timetable</title>
<!-- Tailwind CSS from CDN -->
<script src="[Link]
<style>
/* Custom styles for animations */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Top Bar */
header {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 50;
background-color: rgba(31, 41, 55, 0.8);
backdrop-filter: blur(12px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0,
0, 0, 0.06);
padding: 1rem;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
/* Main Content */
main {
flex-grow: 1;
width: 100%;
max-width: 80rem;
margin-left: auto;
margin-right: auto;
padding-top: 6rem;
padding-bottom: 2rem;
padding-left: 1rem;
padding-right: 1rem;
}
/* Auth Form */
.auth-container {
background-color: #1f2937;
padding: 2rem;
border-radius: 1rem;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px
rgba(0, 0, 0, 0.04);
border: 1px solid #374151;
width: 100%;
max-width: 28rem;
margin-left: auto;
margin-right: auto;
}
.auth-input-container {
position: relative;
}
.auth-input {
width: 100%;
padding: 0.75rem;
padding-left: 2.5rem;
background-color: #374151;
border-radius: 0.75rem;
border: 1px solid #4b5563;
outline: none;
}
.auth-input:focus {
box-shadow: 0 0 0 2px rgba(129, 140, 248, 0.5);
}
.auth-icon {
position: absolute;
left: 0.75rem;
top: 50%;
transform: translateY(-50%);
color: #9ca3af;
}
.auth-button {
width: 100%;
padding: 0.75rem;
border-radius: 0.75rem;
font-weight: bold;
font-size: 1.125rem;
color: white;
background-color: #4f46e5;
}
.auth-button:hover {
background-color: #4338ca;
}
/* Dashboard */
.dashboard-header {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: flex-start;
margin-bottom: -22px;
gap: 1rem;
}
.tab-button {
padding: 0.75rem 1.5rem;
border-radius: 0.75rem;
font-weight: 600;
font-size: 1.125rem;
}
.active-tab {
background-color: #4f46e5;
color: white;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0,
0, 0, 0.05);
}
.inactive-tab {
background-color: #374151;
color: #d1d5db;
}
.inactive-tab:hover {
background-color: #4b5563;
}
.logout-button {
padding: 0.75rem 1.5rem;
border-radius: 0.75rem;
font-weight: bold;
font-size: 1.125rem;
color: white;
background-color: #dc2626;
}
.logout-button:hover {
background-color: #b91c1c;
}
/* Timetable */
.timetable-container {
background-color: #1f2937;
padding: 1rem;
border-radius: 1rem;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px
rgba(0, 0, 0, 0.04);
border: 1px solid #374151;
}
.timetable-grid {
display: grid;
grid-template-columns: repeat(6, 1fr);
gap: 1rem;
}
.timetable-day-header {
text-align: center;
font-weight: bold;
font-size: 1.125rem;
color: #d1d5db;
border-bottom-width: 2px;
border-color: #818cf8;
padding-bottom: 0.5rem;
}
.timetable-day {
background-color: #374151;
padding: 1rem;
border-radius: 0.75rem;
min-height: 150px;
border: 1px solid #4b5563;
}
.timetable-item {
position: relative;
padding: 0.75rem;
margin-bottom: 0.5rem;
border-radius: 0.5rem;
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0,
0.06);
margin-bottom: 0.5rem; /* Adds space below each item */
transition: transform 0.2s ease, box-shadow 0.2s ease; /* Smooth hover effects
*/
}
.timetable-item:hover {
transform: translateY(-2px); /* Slight lift effect on hover */
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); /* Shadow on hover */
}
.lecture-item {
background-color: #4f46e5;
}
.break-item {
background-color: #4b5563;
}
/* Notifications */
.notification-item {
position: relative;
background-color: #374151;
padding: 1rem;
border-radius: 0.75rem;
border: 1px solid #4b5563;
}
.notification-item:hover {
background-color: #4b5563;
}
/* Modals */
.modal-overlay {
position: fixed;
inset: 0;
z-index: 50;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(8px);
}
.modal-container1{
background-color: #1f2937;
padding: 1.5rem;
border-radius: 1rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid #374151;
width: 100%;
max-width: 30rem;
position: relative;
animation: fadeIn 0.3s ease-out;
}
.modal-container {
background-color: #1f2937;
padding: 1.5rem;
border-radius: 1rem;
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
border: 1px solid #374151;
width: 100%;
max-width: 55rem;
position: relative;
animation: fadeIn 0.3s ease-out;
}
.modal-close-button {
position: absolute;
top: 1rem;
right: 1rem;
color: #9ca3af;
}
.modal-close-button:hover {
color: white;
}
#close-edit-department-modal{
width: 2.5rem;
height: 2.5rem;
font-size: 30px;
display: flex;
align-items: center;
justify-content: center;
padding: 0.5rem;
border-radius: 50%;
transition: all 0.2s ease;
}
#close-view-departments-modal {
width: 2.5rem;
height: 2.5rem;
font-size: 30px;
display: flex;
align-items: center;
justify-content: center;
padding: 0.5rem;
border-radius: 50%;
transition: all 0.2s ease;
}
#close-view-students-modal {
width: 2.5rem;
height: 2.5rem;
font-size: 30px;
display: flex;
align-items: center;
justify-content: center;
padding: 0.5rem;
border-radius: 50%;
transition: all 0.2s ease;
}
.modal-form {
display: flex;
flex-direction: column;
gap: 1rem;
}
.modal-form-group {
display: flex;
gap: 1rem;
}
.modal-form-input {
width: 100%;
padding: 0.5rem;
border-radius: 0.5rem;
background-color: #374151;
color: white;
}
.modal-form-select {
width: 100%;
padding: 0.5rem;
border-radius: 0.5rem;
background-color: #374151;
color: white;
}
.modal-form-button {
width: 100%;
padding: 0.5rem;
border-radius: 0.5rem;
font-weight: bold;
color: white;
background-color: #4f46e5;
}
.modal-form-button:hover {
background-color: #4338ca;
}
/* Preview Panels */
.preview-panel {
width: 512px;
background-color: #374151;
padding: 1rem;
border-radius: 0.5rem;
}
.preview-item {
padding: 0.75rem;
border-radius: 0.5rem;
margin-bottom: 0.5rem;
margin-bottom: 0.5rem; /* Consistent spacing */
/* Faculty Checkboxes */
.faculty-checkbox-container {
background-color: #374151;
padding: 0.5rem;
border-radius: 0.5rem;
max-height: 10rem;
overflow-y: auto;
}
.faculty-checkbox-item {
display: flex;
align-items: center;
margin-bottom: 0.25rem;
}
/* Subject Inputs */
.subject-input-container {
display: flex;
}
.subject-input {
width: 100%;
padding: 0.5rem;
border-radius: 0.5rem;
background-color: #374151;
color: white;
}
.add-subject-button {
margin-left: 0.5rem;
padding-left: 0.75rem;
padding-right: 0.75rem;
border-radius: 0.5rem;
background-color: #4f46e5;
color: white;
}
.add-subject-button:hover {
background-color: #4338ca;
}
.remove-subject-button {
margin-left: 0.5rem;
padding-left: 0.75rem;
padding-right: 0.75rem;
border-radius: 0.5rem;
background-color: #dc2626;
color: white;
}
.remove-subject-button:hover {
background-color: #b91c1c;
}
/* Tables */
.data-table {
width: 100%;
text-align: left;
}
.data-table thead {
position: sticky;
top: 0;
background-color: #374151;
}
.data-table th {
padding: 0.75rem;
font-weight: 600;
}
.data-table td {
padding: 0.75rem;
}
.data-table tr {
border-bottom-width: 1px;
border-color: #374151;
}
.data-table tr:hover {
background-color: #374151;
}
/* Utility Classes */
.animate-fade-in-up {
animation: fadeIn 0.3s ease-out;
}
.dragging {
opacity: 0.5;
}
.day-highlight {
border: 2px solid #818cf8 !important;
}
.delete-button {
position: absolute;
top: -7px;
right: -5px;
color: white;
background-color: #d95555;
border-radius: 8px;
width: 1.5rem;
height: 1.5rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 700;
cursor: pointer;
border: none;
outline: none;
}
.delete-button:hover {
background-color: #dc2626;
}
.space-y-8 {
margin-top: -20px;
}
.form-checkbox {
border-radius: 0.25rem;
border-width: 1px;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
width: 1rem;
height: 1rem;
transition: all 0.2s ease;
}
.form-checkbox:checked {
background-color: #818cf8;
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16'
fill='white' xmlns='[Link] d='M5.707 7.293a1 1 0 0
0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4a1 1 0 0 0-1.414-1.414L7 8.586 5.707
7.293z'/%3e%3c/svg%3e");
background-position: center;
background-repeat: no-repeat;
background-size: 75%;
}
.logout-btn:hover {
background-color: #b91c1c;
}
.notification-btn:hover {
background-color: #15803d; /* green-700 */
}
.view-students-btn {
padding: 0.5rem 1rem;
border-radius: 0.5rem;
font-weight: 600;
font-size: 1rem;
color: white;
background-color: #7c3aed; /* purple-600 */
border: none;
cursor: pointer;
white-space: nowrap;
transition: background-color 0.2s ease;
}
.view-students-btn:hover {
background-color: #6d28d9; /* purple-700 */
}
.notification-item {
position: relative;
padding: 1rem;
padding-right: 3rem; /* Add space for buttons on the right */
}
.notification-item .absolute {
z-index: 10; /* Ensure buttons stay above other content */
margin-top: 7px;
}
.notification-item .[Link]-between {
align-items: flex-start;
gap: 0.5rem;
}
.notification-item .[Link]-gray-800 {
margin-right: 20px;
margin-left: auto; /* Push department badge to the right */
white-space: nowrap; /* Prevent badge text from wrapping */
flex-shrink: 0; /* Prevent badge from shrinking */
}
</style>
</head>
<body>
<div id="app">
<!-- Top Bar -->
<header>
<h1 class="text-xl sm:text-2xl font-bold text-indigo-400">University
Portal</h1>
<div class="flex items-center space-x-4 text-sm sm:text-base">
<span id="current-date" class="font-semibold"></span>
<span id="current-time" class="font-mono bg-gray-700 text-green-400
py-1 px-2 rounded-lg"></span>
</div>
</header>
<script>
function formatTimeForDisplay(time24) {
// Split the time into hours and minutes
const [hours, minutes] = [Link](':').map(Number);
// OK button
const closeBtn = [Link]('close-error-modal-btn');
if (closeBtn) {
[Link]('click', closeModal);
}
// X button
const closeBtnX = [Link]('close-error-modal-x');
if (closeBtnX) {
[Link]('click', closeModal);
}
return 0; // fallback
}
// Constants
const MOCK_ADMINS_KEY = "mockAdmins";
const MOCK_USERS_KEY = "mockUsers";
const TIMETABLE_KEY = "timetableData";
const NOTIFICATIONS_KEY = "notificationsData";
const FACULTY_SUBJECTS_KEY = "facultySubjectsData";
const DEPARTMENTS_KEY = "departmentsData";
const DAYS_OF_WEEK = ['Monday', 'Tuesday', 'Wednesday', 'Thursday',
'Friday', 'Saturday'];
const initialNotifications = [
{ id: 1, title: 'Welcome!', message: 'Welcome to the new digital notice
board.', timestamp: new Date().toISOString() },
{ id: 2, title: 'Exam Timetable', message: 'The mid-term exam schedule
has been updated on the website.', timestamp: new Date([Link]() -
3600000).toISOString() }
];
// State management
let state = {
isLoggedIn: false,
isAdmin: false,
view: 'login',
adminTimetable: [Link](TIMETABLE_KEY, {}),
notifications: [Link](NOTIFICATIONS_KEY,
initialNotifications),
facultySubjects: [Link](FACULTY_SUBJECTS_KEY,
initialFacultySubjects),
departments: [Link](DEPARTMENTS_KEY, initialDepartments),
currentDepartment: '',
currentTime: new Date(),
dragItem: null,
draggedOverDay: null,
currentUser: null
};
// Initial render
updateDateTimeDisplay();
render();
switch ([Link]) {
case 'login':
[Link] = renderAuthForm('login');
break;
case 'register':
[Link] = renderAuthForm('register');
break;
case 'forgot-password':
[Link] = renderAuthForm('forgot-password');
break;
case 'dashboard':
[Link] = renderDashboard();
break;
default:
[Link] = renderAuthForm('login');
}
<button
type="submit"
class="auth-button"
>
${type === 'login' ? 'Login' : type === 'register' ?
'Register' : 'Send OTP'}
</button>
</form>
<div class="dashboard-header-controls">
${[Link] ? `
<select id="department-selector" class="department-selector">
<option value="" disabled ${![Link] ? 'selected' :
''}>Select Department</option>
${[Link](dept => `
<option value="${dept}" ${[Link] === dept ? 'selected'
: ''}>${dept}</option>
`).join('')}
</select>
` : `
<select id="student-department-selector"
class="department-selector" disabled>
<option value="${[Link]?.department || ''}" selected>$
{[Link]?.department || 'No Department'}</option>
</select>
`}
<button id="logout-btn" class="logout-btn">
Logout
</button>
</div>
</div>
// Timetable rendering
function renderTimetable() {
const timetableData = ([Link] ?
[Link][[Link]] || {} :
[Link][[Link]?.department] || {});
return `
<div class="timetable-container">
<div class="flex justify-between items-center mb-6">
<h2 class="text-3xl font-bold text-indigo-400">$
{[Link] ? [Link] : [Link]?.department}</h2>
${[Link] ? `
<div class="flex flex-col sm:flex-row space-y-2
sm:space-y-0 sm:space-x-4">
<button id="add-department-btn" class="modal-form-
button bg-blue-800 hover:bg-blue-900">
+ Add Department
</button>
<button id="view-departments-btn" class="modal-
form-button bg-blue-700 hover:bg-blue-800">
View Departments
</button>
<button id="add-faculty-btn" class="modal-form-
button bg-blue-600 hover:bg-blue-700">
+ Add Faculty
</button>
<button id="view-faculty-btn" class="modal-form-
button bg-purple-600 hover:bg-purple-700">
View Faculty
</button>
<button id="add-lecture-btn" class="modal-form-
button bg-green-600 hover:bg-green-700">
+ Add Lecture
</button>
<button id="add-break-btn" class="modal-form-button
bg-gray-600 hover:bg-gray-700">
+ Add Break
</button>
</div>
` : ''}
</div>
<div class="overflow-x-auto">
<div class="timetable-grid">
${DAYS_OF_WEEK.map(day => `
<div key="${day}" class="timetable-day-header">
${day}
</div>
`).join('')}
if ([Link]) {
// Admins see all notifications
notificationsToShow = [...[Link]];
} else {
// Students see only notifications for their department or 'all'
notifications
notificationsToShow = [Link](n =>
[Link] === [Link]?.department ||
[Link] === 'all' ||
![Link] // Backward compatibility for existing notifications
);
}
return `
<div class="timetable-container">
<div class="flex justify-between items-center mb-6">
<h2 class="text-3xl font-bold text-indigo-400">Notifications</h2>
${[Link] ? `
<button id="add-notification-btn" class="notification-btn">
+ Post Notification
</button>
` : ''}
</div>
<div class="space-y-4">
${[Link] > 0 ? [Link](n => `
<div key="${[Link]}" class="notification-item relative">
<div class="flex justify-between items-start mb-2">
<h3 class="font-bold text-xl text-indigo-300">$
{[Link]}</h3>
${[Link] && [Link] !== 'all' ? `
<span class="text-xs bg-gray-800 px-2 py-1
rounded">${[Link]}</span>
` : ''}
</div>
<p class="text-gray-300">${[Link]}</p>
<p class="text-xs text-gray-400 mt-2">
${new Date([Link]).toLocaleString()}
</p>
${[Link] ? `
<div class="absolute top-2 right-2 flex space-x-1">
<button
onclick="handleEditNotification(${[Link]})"
class="text-white bg-blue-500 rounded-full w-6
h-6 flex items-center justify-center text-xs font-bold hover:bg-blue-600"
>
✏️
</button>
<button
onclick="handleDeleteNotification(${[Link]})"
class="text-white bg-red-500 rounded-full w-6
h-6 flex items-center justify-center text-xs font-bold hover:bg-red-600"
>
×
</button>
</div>
` : ''}
</div>
`).join('') : `
<p class="text-center text-gray-400 p-8">No notifications to
display.</p>
`}
</div>
</div>
`;
}
return `
<div class="timetable-container">
<div class="flex justify-between items-center mb-6">
<h2 class="text-3xl font-bold text-indigo-400">Students - $
{[Link] || 'All Departments'}</h2>
</div>
<div class="overflow-x-auto">
<table class="data-table">
<thead>
<tr>
<th>Username</th>
<th>Email</th>
<th>Department</th>
</tr>
</thead>
<tbody>
${[Link] > 0 ? [Link](user => `
<tr>
<td>${[Link]}</td>
<td>${[Link]}</td>
<td>${[Link]}</td>
</tr>
`).join('') : `
<tr>
<td colspan="3" class="text-center py-4 text-gray-
400">No students found</td>
</tr>
`}
</tbody>
</table>
</div>
</div>
`;
}
function renderAddBreakModal() {
return `
<div class="modal-overlay">
<div class="modal-container">
<h3 class="text-2xl font-bold text-white mb-4">Add New Break - $
{[Link]}</h3>
function renderAddFacultyModal() {
return `
<div class="modal-overlay">
<div class="modal-container1">
<h3 class="text-2xl font-bold text-white mb-4">Add New Faculty
Subject</h3>
<form id="add-faculty-form" class="modal-form">
<div>
<label class="block text-gray-400">Department(s)</label>
<div class="faculty-checkbox-container">
${[Link](dept => `
<div class="faculty-checkbox-item">
<input
type="checkbox"
id="dept-${dept}"
value="${dept}"
class="form-checkbox"
>
<label for="dept-${dept}" class="ml-2 text-
gray-300">${dept}</label>
</div>
`).join('')}
</div>
</div>
<div>
<label class="block text-gray-400">Teacher Name</label>
<input type="text" id="faculty-teacher" required
class="modal-form-input" />
</div>
<div>
<label class="block text-gray-400">Subjects</label>
<div id="subjects-container" class="space-y-2">
<div class="subject-input-container">
<input type="text" class="subject-input"
placeholder="Subject name" />
<button type="button" onclick="addSubjectField()"
class="add-subject-button">+</button>
</div>
</div>
</div>
<button type="submit" class="modal-form-button">
Add Faculty
</button>
</form>
<button id="close-faculty-modal" class="modal-close-button">
<svg xmlns="[Link] width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-
linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
`;
}
function getSelectedDepartments() {
const checkboxes = [Link]('input[type="checkbox"]
[id^="dept-"]:checked');
return [Link](checkboxes).map(cb => [Link]);
}
function getEnteredSubjects() {
const inputs = [Link]('.subject-input');
return [Link](inputs)
.map(input => [Link]())
.filter(subject => [Link] > 0);
}
function renderAddDepartmentModal() {
return `
<div class="modal-overlay">
<div class="modal-container1">
<h3 class="text-2xl font-bold text-white mb-4">Add New
Department</h3>
<form id="add-department-form" class="modal-form">
<div>
<label class="block text-gray-400">Department
Name</label>
<input type="text" id="department-name" required
class="modal-form-input" />
</div>
<button type="submit" class="modal-form-button">
Add Department
</button>
</form>
<button id="close-department-modal" class="modal-close-
button">
<svg xmlns="[Link] width="24"
height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
stroke-linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
`;
}
function renderViewDepartmentsModal() {
return `
<div class="modal-overlay">
<div class="modal-container" style="max-width: 56rem;">
<h3 class="text-2xl font-bold text-white mb-4">Departments
List</h3>
<div class="overflow-y-auto max-h-[60vh]">
<table class="data-table">
<thead>
<tr>
<th>Department Name</th>
<th>Number of Faculty</th>
<th>Number of Classes</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
${[Link]((department, index) => {
const uniqueTeachers = new Set(
[Link]
.filter(f => [Link] === department)
.map(f => [Link])
);
const facultyCount = [Link];
const classCount =
[Link]([Link][department] || {}).flat().length;
return `
<tr class="hover:bg-gray-700" id="department-row-$
{index}">
<td>${department}</td>
<td>${facultyCount}</td>
<td>${classCount}</td>
<td class="text-right">
<button
onclick="handleEditDepartment('$
{department}')"
class="mr-2 text-blue-400 hover:text-
blue-300"
>
Edit
</button>
<button
onclick="handleDeleteDepartment('$
{department}')"
class="text-red-400 hover:text-red-300"
>
Delete
</button>
</td>
</tr>
`;
}).join('')}
</tbody>
</table>
</div>
<button id="close-view-departments-modal" class="modal-close-
button">
×
</button>
</div>
</div>
`;
}
function renderEditDepartmentModal(oldDepartmentName) {
return `
<div class="modal-overlay">
<div class="modal-container1">
<h3 class="text-2xl font-bold text-white mb-4">Edit Department</h3>
<form id="edit-department-form" class="modal-form">
<input type="hidden" id="old-department-name" value="$
{oldDepartmentName}">
<div>
<label class="block text-gray-400">Department Name</label>
<input type="text" id="new-department-name" value="$
{oldDepartmentName}" required class="modal-form-input" />
</div>
<button type="submit" class="modal-form-button">
Update Department
</button>
</form>
<button id="close-edit-department-modal" class="modal-close-
button">
×
</button>
</div>
</div>
`;
}
function handleEditDepartment(departmentName) {
[Link]('.modal-overlay').remove();
[Link]('beforeend',
renderEditDepartmentModal(departmentName));
attachModalEventListeners('edit-department');
}
if ([Link](newName)) {
alert('Department with this name already exists!');
return;
}
// Update timetable
const newTimetable = {...[Link]};
if (newTimetable[oldName]) {
newTimetable[newName] = newTimetable[oldName];
delete newTimetable[oldName];
}
[Link] = newTimetable;
[Link](TIMETABLE_KEY, newTimetable);
[Link]('.modal-overlay').remove();
[Link]('beforeend', renderViewDepartmentsModal());
attachModalEventListeners('view-departments');
}
function renderEditNotificationModal(notification) {
return `
<div class="modal-overlay">
<div class="modal-container">
<h3 class="text-2xl font-bold text-white mb-4">Edit
Notification</h3>
<form id="edit-notification-form" class="modal-form">
<input type="hidden" id="edit-notification-id" value="$
{[Link]}">
<div>
<label class="block text-gray-400">Department</label>
<select id="edit-notification-department" class="modal-
form-select" required>
${[Link](dept => `
<option value="${dept}" ${[Link]
=== dept ? 'selected' : ''}>${dept}</option>
`).join('')}
<option value="all" ${[Link] === 'all'
? 'selected' : ''}>All Departments</option>
</select>
</div>
<div>
<label class="block text-gray-400">Title</label>
<input type="text" id="edit-notification-title" value="$
{[Link]}" required class="modal-form-input" />
</div>
<div>
<label class="block text-gray-400">Message</label>
<textarea id="edit-notification-message" required
class="modal-form-input" rows="4">${[Link]}</textarea>
</div>
<button type="submit" class="modal-form-button">
Update Notification
</button>
</form>
<button id="close-edit-notification-modal" class="modal-close-
button">
<svg xmlns="[Link] width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-
linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
`;
}
function renderViewFacultyModal() {
// Group subjects by teacher and include all departments
const facultyByTeacher = {};
[Link](faculty => {
if (!facultyByTeacher[[Link]]) {
facultyByTeacher[[Link]] = {
subjects: [],
departments: []
};
}
// Add unique subjects
if (!facultyByTeacher[[Link]].[Link]([Link]))
{
facultyByTeacher[[Link]].[Link]([Link]);
}
// Add unique departments
if (!
facultyByTeacher[[Link]].[Link]([Link])) {
facultyByTeacher[[Link]].[Link]([Link]);
}
});
return `
<div class="modal-overlay">
<div class="modal-container" style="max-width: 56rem;">
<h3 class="text-2xl font-bold text-white mb-4">Faculty List</h3>
<div class="overflow-y-auto max-h-[60vh]">
<table class="data-table">
<thead>
<tr>
<th>Teacher</th>
<th>Subjects</th>
<th>Departments</th>
<th class="text-right">Actions</th>
</tr>
</thead>
<tbody>
${[Link](facultyByTeacher).map(([teacher,
data], index) => {
return `
<tr class="hover:bg-gray-700" id="faculty-row-$
{index}">
<td>${teacher}</td>
<td>${[Link](', ')}</td>
<td>${[Link](', ')}</td>
<td class="text-right">
<button
onclick="handleEditFacultyByTeacher('${teacher}')" class="mr-2 text-blue-400
hover:text-blue-300">
Edit
</button>
<button
onclick="handleDeleteFacultyByTeacher('${teacher}')" class="text-red-400
hover:text-red-300">
Delete
</button>
</td>
</tr>
`;
}).join('')}
</tbody>
</table>
</div>
<button id="close-view-faculty-modal" class="modal-close-button">
<svg xmlns="[Link] width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-
linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
`;
}
function renderEditFacultyModal(index) {
const faculty = [Link][index];
return `
<div class="modal-overlay">
<div class="modal-container1">
<h3 class="text-2xl font-bold text-white mb-4">Edit Faculty</h3>
<form id="edit-faculty-form" class="modal-form">
<input type="hidden" id="edit-faculty-index" value="${index}">
<div>
<label class="block text-gray-400">Department</label>
<select id="edit-faculty-department" class="modal-form-
select">
${[Link](dept => `
<option value="${dept}" ${[Link] ===
dept ? 'selected' : ''}>${dept}</option>
`).join('')}
</select>
</div>
<div>
<label class="block text-gray-400">Subject</label>
<input type="text" id="edit-faculty-subject" value="$
{[Link]}" required class="modal-form-input" />
</div>
<div>
<label class="block text-gray-400">Teacher</label>
<input type="text" id="edit-faculty-teacher" value="$
{[Link]}" required class="modal-form-input" />
</div>
<button type="submit" class="modal-form-button">
Update Faculty
</button>
</form>
<button id="close-edit-faculty-modal" class="modal-close-button">
<svg xmlns="[Link] width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-
linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
`;
}
function renderErrorModal(message) {
return `
<div class="fixed inset-0 z-50 flex items-center justify-center p-4 bg-
black bg-opacity-50 backdrop-blur-sm">
<div class="bg-gray-800 p-6 rounded-2xl shadow-2xl border border-red-
500 w-full max-w-md relative animate-fade-in-up">
<div class="flex items-start">
<div class="flex-shrink-0">
<svg class="h-6 w-6 text-red-400"
xmlns="[Link] fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round"
stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-
3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
</div>
<div class="ml-3">
<h3 class="text-lg font-medium text-white">Time
Conflict</h3>
<div class="mt-2 text-sm text-gray-300">
<p>${message}</p>
</div>
</div>
</div>
<div class="mt-4 flex justify-end">
<button id="close-error-modal-btn" type="button" class="px-4
py-2 rounded-lg text-sm font-medium text-white bg-red-600 hover:bg-red-700
focus:outline-none focus:ring-2 focus:ring-red-500 transition-colors">
OK
</button>
</div>
<button id="close-error-modal-x" class="absolute top-4 right-4
text-gray-400 hover:text-white transition-colors">
<svg xmlns="[Link] width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-
linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
`;
}
// Event handlers
function handleEditNotification(id) {
const notification = [Link](n => [Link] === id);
if (!notification) return;
[Link]('.modal-overlay')?.remove();
[Link]('beforeend',
renderEditNotificationModal(notification));
attachModalEventListeners('edit-notification');
}
if (user) {
[Link] = true;
[Link] = userType === 'admin';
[Link] = 'dashboard';
[Link] = 'timetable';
[Link] = user;
[Link] = [Link] || '';
render();
return true;
}
return false;
}
function handleEditFaculty(index) {
[Link]('.modal-overlay').remove();
[Link]('beforeend', renderEditFacultyModal(index));
attachModalEventListeners('edit-faculty');
}
function handleDeleteFaculty(index) {
if (confirm('Are you sure you want to delete this faculty?')) {
const newFacultySubjects = [...[Link]];
[Link](index, 1);
[Link] = newFacultySubjects;
[Link](FACULTY_SUBJECTS_KEY, newFacultySubjects);
function handleDeleteDepartment(department) {
// Prevent deletion of default departments
if (confirm(`Are you sure you want to delete the ${department} department? This
will also remove all associated faculty and timetable entries.`)) {
// Remove department from departments list
const newDepartments = [Link](d => d !== department);
[Link] = newDepartments;
[Link](DEPARTMENTS_KEY, newDepartments);
function handleEditFacultyByTeacher(teacher) {
// Find all faculty entries for this teacher
const facultyEntries = [Link](f => [Link] ===
teacher);
return `
<div class="modal-overlay">
<div class="modal-container1">
<h3 class="text-2xl font-bold text-white mb-4">Edit Faculty - $
{teacher}</h3>
<form id="edit-faculty-teacher-form" class="modal-form">
<input type="hidden" id="original-teacher-name" value="$
{teacher}">
<div>
<label class="block text-gray-400">Department(s)</label>
<div class="faculty-checkbox-container">
${[Link](dept => `
<div class="faculty-checkbox-item">
<input
type="checkbox"
id="edit-dept-${dept}"
value="${dept}"
${[Link](dept) ? 'checked' :
''}
class="form-checkbox"
>
<label for="edit-dept-${dept}" class="ml-2
text-gray-300">${dept}</label>
</div>
`).join('')}
</div>
</div>
<div>
<label class="block text-gray-400">Teacher Name</label>
<input type="text" id="edit-teacher-name" value="$
{teacher}" required class="modal-form-input" />
</div>
<div>
<label class="block text-gray-400">Subjects</label>
<div id="edit-subjects-container" class="space-y-2">
${[Link]((subject, i) => `
<div class="subject-input-container">
<input type="text" value="${subject}"
class="subject-input" placeholder="Subject name" />
<button type="button" onclick="${i === 0 ?
'addEditSubjectField()' : '[Link]()'}" class="${i === 0 ? 'add-
subject-button' : 'remove-subject-button'}">
${i === 0 ? '+' : '×'}
</button>
</div>
`).join('')}
</div>
</div>
<button type="submit" class="modal-form-button">
Update
</button>
</form>
<button id="close-edit-faculty-teacher-modal" class="modal-close-
button">
<svg xmlns="[Link] width="24" height="24"
viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-
linecap="round" stroke-linejoin="round">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
</div>
`;
}
attachModalEventListeners('edit-faculty-teacher');
}
function handleDeleteFacultyByTeacher(teacher) {
if (confirm(`Are you sure you want to delete all entries for ${teacher}?`)) {
const newFacultySubjects = [Link](f => [Link] !==
teacher);
[Link] = newFacultySubjects;
[Link](FACULTY_SUBJECTS_KEY, newFacultySubjects);
function handleRegistration(user) {
const users = [Link](MOCK_USERS_KEY, []);
if ([Link](u => [Link] === [Link])) {
return false; // Email already registered
}
const newUsers = [...users, user];
[Link](MOCK_USERS_KEY, newUsers);
return true;
}
function handleLogout() {
[Link] = false;
[Link] = false;
[Link] = 'login';
[Link] = null;
render();
}
function handleDragEnd(e) {
if (![Link]) return;
[Link]('dragging');
[Link] = null;
[Link] = null;
render();
}
// Check if the item being moved would conflict with existing items
if ([Link]) {
const [startTime, endTime] = [Link](' - ');
if (hasTimeConflict(dropDay, startTime, endTime, [Link]))
{
showTimeConflictError('Cannot move this item - it would conflict with
an existing schedule.');
[Link] = null;
[Link] = null;
render();
return;
}
}
newTimetable[[Link]][dropDay] = [...
(newTimetable[[Link]][dropDay] || []), itemToMove];
[Link] = newTimetable;
[Link](TIMETABLE_KEY, newTimetable);
[Link] = null;
[Link] = null;
render();
}
// Dashboard events
const timetableTab = [Link]('timetable-tab');
if (timetableTab) {
[Link]('click', () => {
[Link] = 'timetable';
render();
});
}
// Timetable events
const addDepartmentBtn = [Link]('add-department-btn');
if (addDepartmentBtn) {
[Link]('click', () => {
[Link]('beforeend',
renderAddDepartmentModal());
attachModalEventListeners('department');
});
}
// Notifications events
const addNotificationBtn = [Link]('add-notification-
btn');
if (addNotificationBtn) {
[Link]('click', () => {
[Link]('beforeend',
renderAddNotificationModal());
attachModalEventListeners('notification');
});
}
const viewFacultyBtn = [Link]('view-faculty-btn');
if (viewFacultyBtn) {
[Link]('click', () => {
[Link]('beforeend', renderViewFacultyModal());
attachModalEventListeners('view-faculty');
});
}
const timetable =
[Link][[Link]]?.[day] || [];
[Link]((item, itemIndex) => {
const itemElement = [Link](`item-$
{dayIndex}-${itemIndex}`);
if (itemElement) {
[Link]('dragstart', (e) =>
handleDragStart(e, dayIndex, itemIndex));
[Link]('dragend', handleDragEnd);
}
});
});
}
}
if ([Link] === 0) {
[Link] = '<p class="text-gray-400 text-center py-4">No
classes scheduled for this day</p>';
return;
}
// Initial update
updateSchedulePreview();
// Update when day changes
[Link]('lecture-day').addEventListener('change',
updateSchedulePreview);
const newLecture = {
type: 'lecture',
subject,
teacher,
time: `${formattedStartTime} - ${formattedEndTime}`
};
const newTimetable = {
...[Link],
[[Link]]: {
...[Link][[Link]],
[day]: [...([Link][[Link]][day]
|| []), newLecture]
}
};
[Link] = newTimetable;
[Link](TIMETABLE_KEY, newTimetable);
[Link]('.modal-overlay').remove();
render();
});
if ([Link] === 0) {
[Link] = '<p class="text-gray-400 text-center py-
4">No classes scheduled for this day</p>';
return;
}
// Initial update
updateBreakSchedulePreview();
const newBreak = {
type: 'break',
subject: 'Break',
time: `${formattedStartTime} - ${formattedEndTime}`
};
const newTimetable = {
...[Link],
[[Link]]: {
...[Link][[Link]],
[day]: [...([Link][[Link]][day]
|| []), newBreak]
}
};
[Link] = newTimetable;
[Link](TIMETABLE_KEY, newTimetable);
[Link]('.modal-overlay').remove();
render();
});
const newNotification = {
id: [Link](),
title,
message,
department, // Store the department with the notification
timestamp: new Date().toISOString()
};
if ([Link] === 0) {
alert('Please select at least one department!');
return;
}
if ([Link] === 0) {
alert('Please enter at least one subject!');
return;
}
if (!teacher) {
alert('Please enter teacher name!');
return;
}
[Link](department => {
[Link](subject => {
// Check if this combination already exists
if () {
[Link]({ subject, teacher, department });
addedCount++;
}
});
});
if (addedCount === 0) {
alert('All these faculty-subject-department combinations already
exist!');
return;
}
[Link] = newFacultySubjects;
[Link](FACULTY_SUBJECTS_KEY, newFacultySubjects);
[Link]('.modal-overlay').remove();
render();
});
}
if ([Link](departmentName)) {
alert('This department already exists!');
return;
}
[Link]('.modal-overlay').remove();
render();
});
}
[Link] = newFacultySubjects;
[Link](FACULTY_SUBJECTS_KEY, newFacultySubjects);
if ([Link] === 0) {
alert('Please select at least one department!');
return;
}
if ([Link] === 0) {
alert('Please enter at least one subject!');
return;
}
if (!newTeacher) {
alert('Please enter teacher name!');
return;
}
[Link] = newFacultySubjects;
[Link](FACULTY_SUBJECTS_KEY, newFacultySubjects);
[Link] = updatedNotifications;
[Link](NOTIFICATIONS_KEY, updatedNotifications);
[Link]('.modal-overlay').remove();
render();
});
}
function getEditSelectedDepartments() {
const checkboxes = [Link]('input[type="checkbox"][id^="edit-
dept-"]:checked');
return [Link](checkboxes).map(cb => [Link]);
}
function getEditEnteredSubjects() {
const inputs = [Link]('.subject-input');
return [Link](inputs)
.map(input => [Link]())
.filter(subject => [Link] > 0);
}
[Link] = handleDeleteItem;
[Link] = handleDeleteNotification;
[Link] = handleEditFaculty;
[Link] = handleDeleteFaculty;
[Link] = handleEditNotification;
[Link] = handleDeleteDepartment;
[Link] = handleEditDepartment;
</script>
</body>
</html>