diff --git a/client/src/App.js b/client/src/App.js
index 978e0d2..3c01ec7 100644
--- a/client/src/App.js
+++ b/client/src/App.js
@@ -13,9 +13,12 @@ import CourseTable from "./Pages/CourseTable";
import ConsolidatedTable from "./Pages/ConsolidatedTable";
import CourseConsolidated from "./Pages/courseConsolidated";
import PrivateRoute from "./components/PrivateRoute";
+import TokenRefresher from "./components/TokenRefresher";
function App() {
return (
+ <>
+
}>
} />} />
@@ -28,6 +31,7 @@ function App() {
} />} />
} />} />
+ >
);
}
diff --git a/client/src/Pages/ConsolidatedTable.jsx b/client/src/Pages/ConsolidatedTable.jsx
index 2b9018f..c8e89eb 100644
--- a/client/src/Pages/ConsolidatedTable.jsx
+++ b/client/src/Pages/ConsolidatedTable.jsx
@@ -6,39 +6,39 @@ import Navbar from "./Navbar";
const styles = {
header: {
- background: '#003366',
- color: 'white',
- padding: '20px 0',
- textAlign: 'center',
- fontSize: '24px',
- marginBottom: '0',
+ background: "#003366",
+ color: "white",
+ padding: "20px 0",
+ textAlign: "center",
+ fontSize: "24px",
+ marginBottom: "0",
},
buttonRow: {
- display: 'flex',
- justifyContent: 'space-around',
- alignItems: 'center',
- padding: '10px 0',
- margin: '0',
- backgroundColor: '#003366',
- boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)'
+ display: "flex",
+ justifyContent: "space-around",
+ alignItems: "center",
+ padding: "10px 0",
+ margin: "0",
+ backgroundColor: "#003366",
+ boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
},
button: {
- padding: '10px 20px',
- borderRadius: '5px',
- color: 'white',
- border: 'none',
- cursor: 'pointer',
- fontSize: '16px',
- flex: '1',
+ padding: "10px 20px",
+ borderRadius: "5px",
+ color: "white",
+ border: "none",
+ cursor: "pointer",
+ fontSize: "16px",
+ flex: "1",
},
bulkDownloadButton: {
- backgroundColor: '#3fb5a3',
+ backgroundColor: "#3fb5a3",
},
downloadButton: {
- backgroundColor: '#28a745',
+ backgroundColor: "#28a745",
},
emailButton: {
- backgroundColor: '#ff6f61',
+ backgroundColor: "#ff6f61",
},
tableContainer: {
maxHeight: "70vh",
@@ -77,11 +77,9 @@ const styles = {
},
main: {
width: "100%",
- }
+ },
};
-
-
const ConsolidatedTable = () => {
const [searchQuery, setSearchQuery] = useState(""); // State for search input
const [data, setData] = useState([]);
@@ -94,7 +92,8 @@ const ConsolidatedTable = () => {
const fetchData = async () => {
try {
const response = await axios.get(
- "http://localhost:8080/api/table/consolidated-table"
+ "http://localhost:8080/api/table/consolidated-table",
+ { withCredentials: true }
);
setData(response.data);
setLoading(false);
@@ -113,8 +112,7 @@ const ConsolidatedTable = () => {
// Extract unique faculty names and filter based on the search query
const filteredTeachers = [...new Set(data.map((row) => row.Name))].filter(
- (teacher) =>
- teacher.toLowerCase().includes(searchQuery.toLowerCase()) // Filter by search query
+ (teacher) => teacher.toLowerCase().includes(searchQuery.toLowerCase()) // Filter by search query
);
// Pagination logic applied to filtered teachers
@@ -151,7 +149,8 @@ const ConsolidatedTable = () => {
const facultyId = teacherData[0].facultyId;
try {
const response = await axios.get(
- `http://localhost:8080/api/faculty/${facultyId}`
+ `http://localhost:8080/api/faculty/${facultyId}`,
+ { withCredentials: true }
);
const facultyEmail = response.data.email;
const workbook = createExcelBook(teacherData, teacher);
@@ -259,9 +258,7 @@ const ConsolidatedTable = () => {
)
}
>
-
+
{teacher}'s Table
diff --git a/client/src/Pages/Login.jsx b/client/src/Pages/Login.jsx
index e9646cd..c9bf093 100644
--- a/client/src/Pages/Login.jsx
+++ b/client/src/Pages/Login.jsx
@@ -1,4 +1,4 @@
-import React, { useEffect , useState } from "react";
+import React, { useEffect, useState } from "react";
import { Container, Col, Row } from "react-bootstrap";
import { FcGoogle } from "react-icons/fc";
import axios from "axios";
@@ -18,7 +18,6 @@ function AuthPage() {
const notifyError = (message) => {
toast.error(message);
};
-
function ToggleSign(event) {
event.preventDefault();
@@ -40,38 +39,39 @@ function AuthPage() {
async function handleSubmit(event) {
event.preventDefault();
- if (!formData.username.trim() && signin) {
- notifyError("Username cannot be empty");
- return;
- }
+ if (!formData.username.trim() && signin) {
+ notifyError("Username cannot be empty");
+ return;
+ }
- const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
- if (!emailRegex.test(formData.email)) {
- notifyError("Enter a valid email address");
- return;
- }
+ const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
+ if (!emailRegex.test(formData.email)) {
+ notifyError("Enter a valid email address");
+ return;
+ }
- // Check password length
- if (formData.password.length < 8) {
- notifyError("Password must be at least 8 characters long");
- return;
- }
+ // Check password length
+ if (formData.password.length < 8) {
+ notifyError("Password must be at least 8 characters long");
+ return;
+ }
try {
const response = await axios.post(
- `http://localhost:8080/api/${
- !signin ? "login" : "register"
- }`,
- formData
+ `http://localhost:8080/api/${!signin ? "login" : "register"}`,
+ formData,
+ { withCredentials: true }
);
- const { user } = response.data;
- delete user.password;
- const gravatarUrl = `https://www.gravatar.com/avatar/${md5(
- user.email
- )}?d=identicon`;
- user.profilePicture = gravatarUrl;
- localStorage.setItem("user", JSON.stringify(user));
- window.location.href = "/Welcom";
+ if (response.status === 200) {
+ const { user } = response.data;
+ delete user.password;
+ const gravatarUrl = `https://www.gravatar.com/avatar/${md5(
+ user.email
+ )}?d=identicon`;
+ user.profilePicture = gravatarUrl;
+
+ window.location.href = "/Welcome";
+ }
} catch (error) {
console.error("Authentication error:", error);
if (
@@ -88,11 +88,9 @@ function AuthPage() {
const handleGoogleLogin = (event) => {
event.preventDefault();
- window.location.href =
- "http://localhost:8080/auth/google";
+ window.location.href = "http://localhost:8080/auth/google";
};
-
return (
<>
diff --git a/client/src/Pages/Navbar.jsx b/client/src/Pages/Navbar.jsx
index 24bdb40..83dfe56 100644
--- a/client/src/Pages/Navbar.jsx
+++ b/client/src/Pages/Navbar.jsx
@@ -1,9 +1,26 @@
import React from "react";
import { FaUserCircle } from "react-icons/fa";
-import { NavLink } from "react-router-dom"; // Import NavLink for navigation
+import { NavLink, useNavigate } from "react-router-dom"; // Import NavLink for navigation
import "./Navbar.css"; // Navbar-specific styles
+import axios from "axios";
const Navbar = () => {
+ const navigate = useNavigate();
+
+ // Handle logout functionality
+ const handleLogout = async () => {
+ try {
+ // Call the logout API
+ await axios.get("http://localhost:8080/auth/logout", { withCredentials: true });
+
+ // Redirect to the login page after successful logout
+ navigate("/");
+ } catch (error) {
+ console.error("Error during logout:", error);
+ alert("Failed to log out. Please try again.");
+ }
+ };
+
return (