} />} />
>
);
diff --git a/client/src/Pages/AdminCoursePage.jsx b/client/src/Pages/AdminCoursePage.jsx
new file mode 100644
index 0000000..f7a4eea
--- /dev/null
+++ b/client/src/Pages/AdminCoursePage.jsx
@@ -0,0 +1,313 @@
+import React, { useState, useEffect } from 'react';
+import axios from 'axios';
+import Navbar from './Navbar';
+import { toast, ToastContainer } from "react-toastify";
+import 'react-toastify/dist/ReactToastify.css';
+import { useNavigate } from 'react-router-dom';
+
+export const AdminCoursePage = () => {
+ const [courses, setCourses] = useState([]);
+ const [showForm, setShowForm] = useState(false);
+ const [isEditMode, setIsEditMode] = useState(false);
+ const [searchQuery, setSearchQuery] = useState('');
+ const [isLoading, setIsLoading] = useState(true);
+ const [currentCourse, setCurrentCourse] = useState({
+ courseId: '',
+ name: '',
+ department: '',
+ program: '',
+ scheme: '',
+ semester: '',
+ status: 'not submitted',
+ });
+ const navigate = useNavigate();
+
+ // Fetch all courses
+ useEffect(() => {
+ const checkAdmin = async () => {
+ try {
+ const res = await axios.get("http://localhost:8080/api/me", { withCredentials: true });
+ if (!res.data.isAdmin) {
+ handleUnauthorizedAccess();
+ } else {
+ setIsLoading(false);
+ }
+ } catch (error) {
+ console.error("Unauthorized access:", error);
+ handleUnauthorizedAccess();
+ }
+ };
+ fetchCourses();
+ checkAdmin();
+ }, []);
+
+ const handleUnauthorizedAccess = async () => {
+ try {
+ toast.warning("Unauthorized access. Logging out...", { position: "top-center" });
+
+ // Attempt to log out
+ await axios.get("http://localhost:8080/auth/logout", { withCredentials: true });
+
+ // Delay redirection to show the toast message
+ setTimeout(() => {
+ navigate("/"); // Redirect to login
+ }, 1500);
+ } catch (error) {
+ console.error("Error during unauthorized access handling:", error);
+ }
+ };
+
+
+ // Fetch all courses after confirming admin status
+ useEffect(() => {
+ if (!isLoading) {
+ fetchCourses();
+ }
+ }, [isLoading]);
+
+ const fetchCourses = async () => {
+ try {
+ const res = await axios.get('http://localhost:8080/api/courses');
+ setCourses(res.data);
+ } catch (error) {
+ console.error("Error fetching courses: ", error);
+ }
+ };
+
+ // Add or Update Course
+ const handleAddOrUpdateCourse = async (e) => {
+ e.preventDefault();
+
+ try {
+ if (isEditMode) {
+ await axios.put(`http://localhost:8080/api/courses/${currentCourse.courseId}`, currentCourse);
+ toast.success('Course updated successfully!', { position: 'top-center' });
+ } else {
+ await axios.post('http://localhost:8080/api/courses', currentCourse);
+ toast.success('Course added successfully!', { position: 'top-center' });
+ }
+ resetForm();
+ fetchCourses();
+ } catch (error) {
+ console.error("Error adding/updating course:", error);
+ toast.error("An error occurred!", { position: 'top-center' });
+ }
+ };
+
+ // Delete Course
+ const handleDeleteCourse = async (courseId) => {
+ const confirm = window.confirm('⚠️ Are you sure you want to delete this course?');
+ if (confirm) {
+ try {
+ await axios.delete(`http://localhost:8080/api/courses/${courseId}`);
+ fetchCourses();
+ toast.success('Course deleted successfully!', { position: 'top-center' });
+ } catch (error) {
+ console.error("Error deleting course:", error);
+ toast.error("An error occurred!", { position: 'top-center' });
+ }
+ }
+ };
+
+ // Open Form for Edit
+ const handleOpenEditForm = (course) => {
+ setCurrentCourse(course);
+ setIsEditMode(true);
+ setShowForm(true);
+ };
+
+ // Open Form for Add
+ const handleOpenAddForm = () => {
+ resetForm();
+ setIsEditMode(false);
+ setShowForm(true);
+ };
+
+ // Reset form
+ const resetForm = () => {
+ setCurrentCourse({
+ courseId: '',
+ name: '',
+ department: '',
+ program: '',
+ scheme: '',
+ semester: '',
+ status: 'not submitted',
+ });
+ setShowForm(false);
+ };
+
+ const filteredCourses = courses.filter((course) =>
+ course.name.toLowerCase().includes(searchQuery.toLowerCase())
+ );
+
+ if (isLoading) {
+ return Loading...
;
+ }
+
+ return (
+ <>
+
+
+
+
Course Management
+
+
+ setSearchQuery(e.target.value)}
+ style={inputStyle}
+ />
+
+
+
+
+ {showForm && (
+
+
{isEditMode ? 'Edit Course' : 'Add New Course'}
+
+
+ )}
+
+ {/* TABLE DATA */}
+
+
+
+ | Course ID |
+ Name |
+ Department |
+ Program |
+ Scheme |
+ Semester |
+ Status |
+ Actions |
+
+
+
+ {filteredCourses.length > 0 ? (
+ filteredCourses.map((c) => (
+
+ | {c.courseId} |
+ {c.name} |
+ {c.department} |
+ {c.program} |
+ {c.scheme} |
+ {c.semester} |
+ {c.status} |
+
+
+
+ |
+
+ ))
+ ) : (
+
+ |
+ No courses found
+ |
+
+ )}
+
+
+ >
+ );
+};
+
+const tableStyle = {
+ width: '100%',
+ borderCollapse: 'collapse',
+ marginTop: '20px',
+};
+
+const inputStyle = {
+ padding: '10px',
+ width: '250px',
+ borderRadius: '5px',
+ border: '1px solid #ddd',
+ fontSize: '16px',
+ marginRight: '10px',
+};
+
+const formStyle = {
+ backgroundColor: '#fff',
+ padding: '20px',
+ borderRadius: '10px',
+ maxWidth: '500px',
+ margin: '0 auto',
+ boxShadow: '0 5px 20px rgba(0,0,0,0.1)',
+};
+
+const addButtonStyle = {
+ backgroundColor: '#4CAF50',
+ color: '#fff',
+ padding: '10px 15px',
+ borderRadius: '5px',
+ border: 'none',
+ cursor: 'pointer',
+};
+
+const submitButtonStyle = { backgroundColor: '#4CAF50', color: 'white', padding: '10px 20px', borderRadius: '5px' };
+const cancelButtonStyle = { backgroundColor: '#f44336', color: 'white', padding: '10px 20px', borderRadius: '5px' };
+const editButtonStyle = { backgroundColor: '#4CAF50', color: 'white', padding: '5px 10px', borderRadius: '5px' };
+const deleteButtonStyle = { backgroundColor: '#f44336', color: 'white', padding: '5px 10px', borderRadius: '5px' };
+
+export default AdminCoursePage;
diff --git a/client/src/Pages/AdminFacultyPage.jsx b/client/src/Pages/AdminFacultyPage.jsx
index c64b348..98fa3b9 100644
--- a/client/src/Pages/AdminFacultyPage.jsx
+++ b/client/src/Pages/AdminFacultyPage.jsx
@@ -3,6 +3,7 @@ import axios from 'axios';
import Navbar from './Navbar';
import { toast, ToastContainer } from "react-toastify";
import 'react-toastify/dist/ReactToastify.css';
+import { useNavigate } from 'react-router-dom';
export const AdminFacultyPage = () => {
@@ -10,6 +11,7 @@ export const AdminFacultyPage = () => {
const [showForm, setShowForm] = useState(false);
const [isEditMode, setIsEditMode] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
+ const [isLoading, setIsLoading] = useState(true);
const [currentFaculty, setCurrentFaculty] = useState({
facultyId: '',
name: '',
@@ -19,13 +21,51 @@ export const AdminFacultyPage = () => {
courses: [''],
});
const [courses, setcourses] = useState({});
+ const navigate = useNavigate();
// Fetch all faculties
useEffect(() => {
+ const checkAdmin = async () => {
+ try {
+ const res = await axios.get("http://localhost:8080/api/me", { withCredentials: true });
+ console.log(res.data);
+ if (!res.data.isAdmin) {
+ handleUnauthorizedAccess();
+ } else {
+ setIsLoading(false);
+ }
+ } catch (error) {
+ console.error("Unauthorized access:", error);
+ handleUnauthorizedAccess();
+ }
+ };
fetchFaculties();
fetchCourses();
+ checkAdmin();
}, []);
+ const handleUnauthorizedAccess = async () => {
+ try {
+ toast.warning("Unauthorized access. Logging out...", { position: "top-center" });
+
+ // Attempt to log out
+ await axios.get("http://localhost:8080/auth/logout", { withCredentials: true });
+
+ // Delay redirection to show the toast message
+ setTimeout(() => {
+ navigate("/"); // Redirect to login
+ }, 1500);
+ } catch (error) {
+ console.error("Error during unauthorized access handling:", error);
+ }
+};
+
+ useEffect(() => {
+ if (!isLoading) {
+ fetchCourses();
+ }
+ }, [isLoading]);
+
const fetchFaculties = async () => {
const res = await axios.get('http://localhost:8080/api/faculty');
setFaculties(res.data);
@@ -125,6 +165,10 @@ export const AdminFacultyPage = () => {
faculty.name.toLowerCase().includes(searchQuery.toLowerCase())
);
+ if (isLoading) {
+ return Loading...
;
+ }
+
return (
<>
@@ -211,7 +255,7 @@ export const AdminFacultyPage = () => {
/>
-
+
{currentFaculty.courses.map((course, index) => (
diff --git a/client/src/Pages/Navbar.jsx b/client/src/Pages/Navbar.jsx
index 18184e2..30d2401 100644
--- a/client/src/Pages/Navbar.jsx
+++ b/client/src/Pages/Navbar.jsx
@@ -98,6 +98,13 @@ const Navbar = () => {
Faculty
)}
+ {isAdmin && (
+ e.target.style.backgroundColor = "#660000"}
+ onMouseLeave={(e) => e.target.style.backgroundColor = "transparent"}>
+ Courses
+
+ )}