{activeTab === 'timetable' ? 'Academic Planner' : activeTab.replace('_', ' ')}
Manage institution-wide scheduling and resources.
{n.details}
}Sessional Hub
Schedule mid-term assessments and final practical exams for the current semester.
import React, { useState, useEffect, useMemo } from 'react'; import { Calendar, Users, BookOpen, Layout, Plus, Trash2, AlertCircle, Printer, CheckCircle, Clock, MapPin, ChevronRight, Menu, X, ShieldCheck, FileText, Search, AlertTriangle } from 'lucide-react'; // --- Constants & Seed Data --- const BRANCHES = [ { id: 'CE', name: 'Civil Engineering', lateral: false }, { id: 'CE-LE', name: 'Civil Engineering - Lateral Entry', lateral: true }, { id: 'PCE', name: 'Petro Chemical Engineering', lateral: false }, { id: 'PT', name: 'Paint Technology', lateral: false }, ]; const SEMESTERS = [ { no: 1, type: 'ODD' }, { no: 2, type: 'EVEN' }, { no: 3, type: 'ODD' }, { no: 4, type: 'EVEN' }, { no: 5, type: 'ODD' }, { no: 6, type: 'EVEN' }, ]; const DAYS = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT']; const TIME_SLOTS = [ { id: 1, label: 'Period 1', time: '10:00 - 11:00' }, { id: 2, label: 'Period 2', time: '11:00 - 12:00' }, { id: 3, label: 'Period 3', time: '12:00 - 13:00' }, { id: 'LUNCH', label: 'Lunch Break', time: '13:00 - 14:00', isBreak: true }, { id: 4, label: 'Period 4', time: '14:00 - 15:00' }, { id: 5, label: 'Period 5', time: '15:00 - 16:00' }, { id: 6, label: 'Period 6', time: '16:00 - 17:00' }, ]; const INITIAL_FACULTY = [ "Atul Kumar Sharma", "Namrata Pal", "Himmani Khandelwal", "Pushpendra Kumar", "Ashwani Kumar Mishra", "Subodh Saini", "Kanchan Kushwaha", "Bhupendra Pal Singh Yadav", "Anuradha Katiyar", "Vibha Verma", "Satyaveer Singh", "Vivek Kumar Singh", "Yatendra Kumar", "Alka Saxena", "Rajkumar Sharma", "Praveen Mishra", "Priya Sharma", "Shalini Rathore", "Radheshyam Sharma", "Nandkishore Saini", "Ambrikesh Mishra", "Lucky", "Vikas Kumar", "Ashok Kumar", "Hemant Kumar Sharma", "Rajkumar Kushwah", "Amit Kumar Sengar" ].map((name, i) => ({ id: i + 1, name, designation: i === 0 ? 'Principal' : (i === 4 ? 'H.O.D' : (i === 14 ? 'Workshop Superintendent' : 'Lecturer')) })); // Expanded Subjects for Phase 2 readiness const INITIAL_SUBJECTS = [ // Sem 1 & 2 (Common-ish) { id: 101, name: 'Mathematics-I', sem: 1, branches: ['CE', 'PCE', 'PT'], type: 'Theory' }, { id: 102, name: 'Applied Physics-I', sem: 1, branches: ['CE', 'PCE', 'PT'], type: 'Theory' }, { id: 103, name: 'Applied Chemistry', sem: 1, branches: ['CE', 'PCE', 'PT'], type: 'Theory' }, { id: 104, name: 'Communication Skills', sem: 1, branches: ['CE', 'PCE', 'PT'], type: 'Theory' }, { id: 105, name: 'Engineering Graphics', sem: 1, branches: ['CE', 'PCE', 'PT'], type: 'Practical' }, { id: 201, name: 'Mathematics-II', sem: 2, branches: ['CE', 'PCE', 'PT'], type: 'Theory' }, { id: 202, name: 'Applied Physics-II', sem: 2, branches: ['CE', 'PCE', 'PT'], type: 'Theory' }, { id: 203, name: 'Engineering Mechanics', sem: 2, branches: ['CE', 'PCE', 'PT'], type: 'Theory' }, // Sem 3 (Department Specific) { id: 301, name: 'Hydraulics', sem: 3, branches: ['CE', 'CE-LE'], type: 'Theory' }, { id: 302, name: 'Surveying-I', sem: 3, branches: ['CE', 'CE-LE'], type: 'Theory' }, { id: 303, name: 'Concrete Technology', sem: 3, branches: ['CE', 'CE-LE'], type: 'Theory' }, { id: 304, name: 'Chemical Process Calc', sem: 3, branches: ['PCE'], type: 'Theory' }, { id: 305, name: 'Fluid Flow', sem: 3, branches: ['PCE', 'PT'], type: 'Theory' }, { id: 306, name: 'Resins & Polymers', sem: 3, branches: ['PT'], type: 'Theory' }, // Sem 4 { id: 401, name: 'Soil Mechanics', sem: 4, branches: ['CE', 'CE-LE'], type: 'Theory' }, { id: 402, name: 'RCC Design', sem: 4, branches: ['CE', 'CE-LE'], type: 'Theory' }, { id: 403, name: 'Heat Transfer', sem: 4, branches: ['PCE', 'PT'], type: 'Theory' }, { id: 404, name: 'Mass Transfer', sem: 4, branches: ['PCE'], type: 'Theory' }, ]; // --- Main App Component --- export default function App() { const [activeTab, setActiveTab] = useState('dashboard'); const [selectedBranch, setSelectedBranch] = useState(BRANCHES[0]); const [selectedSem, setSelectedSem] = useState(1); const [timetable, setTimetable] = useState([]); const [notifications, setNotifications] = useState([]); // Filtered Subjects for current selection const availableSubjects = useMemo(() => { return INITIAL_SUBJECTS.filter(s => s.sem === selectedSem && s.branches.includes(selectedBranch.id)); }, [selectedSem, selectedBranch]); const addNotification = (msg, type = 'info', details = null) => { const id = Date.now(); setNotifications(prev => [...prev, { id, msg, type, details }]); setTimeout(() => setNotifications(prev => prev.filter(n => n.id !== id)), 6000); }; const handleAddEntry = (day, slotId, subjectId, facultyId, roomId) => { const faculty = INITIAL_FACULTY.find(f => f.id === parseInt(facultyId)); const subject = INITIAL_SUBJECTS.find(s => s.id === parseInt(subjectId)); // Conflict Check 1: Faculty busy in another branch/semester? const facultyConflict = timetable.find(e => e.day === day && e.slotId === slotId && e.facultyId === parseInt(facultyId)); if (facultyConflict) { const conflictBranch = BRANCHES.find(b => b.id === facultyConflict.branchId)?.name; addNotification( `Faculty Conflict!`, 'error', `${faculty?.name} is already assigned to ${conflictBranch} (Sem ${facultyConflict.sem}) in this slot.` ); return; } // Conflict Check 2: Room busy? if (roomId && roomId.trim() !== "") { const roomConflict = timetable.find(e => e.day === day && e.slotId === slotId && e.roomId.toLowerCase() === roomId.toLowerCase()); if (roomConflict) { const conflictBranch = BRANCHES.find(b => b.id === roomConflict.branchId)?.name; addNotification( `Room Conflict!`, 'error', `Room ${roomId} is occupied by ${conflictBranch} (Sem ${roomConflict.sem}).` ); return; } } // Conflict Check 3: Current Branch/Sem already has a class here? const classOverlap = timetable.find(e => e.day === day && e.slotId === slotId && e.branchId === selectedBranch.id && e.sem === selectedSem); if (classOverlap) { addNotification(`Schedule Overlap!`, 'error', `This branch and semester already have a class scheduled for this slot.`); return; } const newEntry = { id: Date.now(), branchId: selectedBranch.id, sem: selectedSem, day, slotId, subjectId: parseInt(subjectId), facultyId: parseInt(facultyId), roomId }; setTimetable(prev => [...prev, newEntry]); addNotification('Entry added successfully', 'success'); }; const removeEntry = (id) => { setTimetable(prev => prev.filter(e => e.id !== id)); }; // Views const Dashboard = () => (
| Branch | Type | Classes |
|---|---|---|
| {b.name} | {b.lateral ? 'LATERAL' : 'REGULAR'} | {timetable.filter(e => e.branchId === b.id).length} slots filled |
No cross-departmental conflicts detected.
|
Time Slot
Schedule
|
{DAYS.map(day => (
{day}
|
))}
|
|---|---|---|
|
{slot.label}
|
{DAYS.map(day => {
const entry = timetable.find(e => e.day === day && e.slotId === slot.id && e.branchId === selectedBranch.id && e.sem === selectedSem);
if (slot.isBreak) return LUNCH | ; return (
{entry ? (
300 ? 'bg-indigo-50 border-indigo-200 text-indigo-900' : 'bg-blue-50 border-blue-200 text-blue-900'}`}>
) : (
)}
{INITIAL_SUBJECTS.find(s => s.id === entry.subjectId)?.name}
|
);
})}
{entryForm.day} • {TIME_SLOTS.find(s => s.id === entryForm.slotId)?.time}
Detailed breakdown of teaching hours, administrative duties, and laboratory oversight.
Manage institution-wide scheduling and resources.
{n.details}
}Schedule mid-term assessments and final practical exams for the current semester.