academicYear logic

This commit is contained in:
amNobodyyy
2025-01-27 23:34:51 +05:30
parent 805d866190
commit 4466b33dff
9 changed files with 138 additions and 88 deletions

View File

@@ -14,7 +14,7 @@ import "react-toastify/dist/ReactToastify.css";
import CourseTable from "./Pages/CourseTable"; import CourseTable from "./Pages/CourseTable";
import GenerateCSV from "./Pages/GenerateCSV"; import GenerateCSV from "./Pages/GenerateCSV";
import ConsolidatedTable from "./Pages/ConsolidatedTable"; import ConsolidatedTable from "./Pages/ConsolidatedTable";
import CourseConsolidated from "./Pages/courseConsolidated"; import CourseConsolidated from "./Pages/CourseConsolidated";
function App() { function App() {
return ( return (

View File

@@ -1,6 +1,6 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useLocation, useParams, useNavigate } from "react-router-dom"; import { useLocation, useParams, useNavigate } from "react-router-dom";
import { fetchFaculties, saveAppointment, updateCourseStatus } from "../api"; import { fetchFaculties, saveAppointment } from "../api";
import "./CourseForm.css"; import "./CourseForm.css";
import "./Navbar.jsx"; import "./Navbar.jsx";
import Navbar from "./Navbar.jsx"; import Navbar from "./Navbar.jsx";
@@ -9,7 +9,7 @@ const CourseForm = () => {
const { id } = useParams(); const { id } = useParams();
const location = useLocation(); const location = useLocation();
const navigate = useNavigate(); const navigate = useNavigate();
const { course } = location.state || {}; const { course, academicYear } = location.state || {};
const [options, setOptions] = useState({ faculties: [] }); const [options, setOptions] = useState({ faculties: [] });
const [suggestions, setSuggestions] = useState({}); const [suggestions, setSuggestions] = useState({});
@@ -32,7 +32,7 @@ const CourseForm = () => {
}); });
const [examPeriod, setExamPeriod] = useState({ const [examPeriod, setExamPeriod] = useState({
year: "", year: academicYear || "",
startMonth: "", startMonth: "",
endMonth: "", endMonth: "",
}); });
@@ -110,6 +110,7 @@ const CourseForm = () => {
if (validateForm()) { if (validateForm()) {
try { try {
const groupedTasks = {}; const groupedTasks = {};
const academicYear = course?.academicYear || examPeriod.year;
Object.entries(tempAssignments).forEach(([field, facultyList]) => { Object.entries(tempAssignments).forEach(([field, facultyList]) => {
facultyList.forEach((faculty) => { facultyList.forEach((faculty) => {
const assignedFaculty = options.faculties.find( const assignedFaculty = options.faculties.find(
@@ -121,7 +122,8 @@ const CourseForm = () => {
facultyId: assignedFaculty.facultyId, facultyId: assignedFaculty.facultyId,
courseId: course?.courseId || id, courseId: course?.courseId || id,
tasks: [], tasks: [],
examPeriod: `${examPeriod.year} (${examPeriod.startMonth} - ${examPeriod.endMonth})`, examPeriod: `${examPeriod.startMonth} - ${examPeriod.endMonth}`,
academicYear,
}; };
} }
groupedTasks[assignedFaculty.facultyId].tasks.push(field); groupedTasks[assignedFaculty.facultyId].tasks.push(field);
@@ -131,14 +133,14 @@ const CourseForm = () => {
const payload = Object.values(groupedTasks); const payload = Object.values(groupedTasks);
await saveAppointment(payload); await saveAppointment(payload);
await updateCourseStatus(course?.courseId || id); // await updateCourseStatus(course?.courseId || id);
const filteredCourses = const filteredCourses =
JSON.parse(localStorage.getItem("filteredCourses")) || []; JSON.parse(localStorage.getItem("filteredCourses")) || [];
navigate("/courses", { navigate("/courses", {
state: { state: {
courses: filteredCourses, courses: filteredCourses,
updatedCourse: { ...course, status: "Submitted" }, academicYear: academicYear,
}, },
}); });
} catch (error) { } catch (error) {
@@ -169,16 +171,12 @@ const CourseForm = () => {
</div> </div>
<div className={errors.examPeriod ? "courseFormErrorSelect" : ""}> <div className={errors.examPeriod ? "courseFormErrorSelect" : ""}>
<label className="courseFormLabel">Exam Period:</label> <label className="courseFormLabel">Exam Period:</label>
<select <input
className="courseFormSelect" type="text"
className="courseFormInput courseFormReadOnly"
value={examPeriod.year} value={examPeriod.year}
onChange={(e) => setExamPeriod({ ...examPeriod, year: e.target.value })} readOnly
> />
<option value="">Year</option>
{[2025, 2026, 2027].map(year => (
<option key={year} value={year}>{year}</option>
))}
</select>
<select <select
className="courseFormSelect" className="courseFormSelect"
value={examPeriod.startMonth} value={examPeriod.startMonth}

View File

@@ -1,57 +1,56 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useLocation, useNavigate } from "react-router-dom"; import { useLocation, useNavigate } from "react-router-dom";
import "./CourseTable.css"; import "./CourseTable.css";
import { fetchCourses } from "../api"; import { fetchCourses, fetchAppointments } from "../api";
import Navbar from "./Navbar"; import Navbar from "./Navbar";
const CourseTable = () => { const CourseTable = () => {
const { state } = useLocation(); const { state } = useLocation();
const [courses, setCourses] = useState(state?.courses || []); const [courses, setCourses] = useState(state?.courses || []);
const [appointments, setAppointments] = useState([]);
const [loading, setLoading] = useState(!state?.courses); const [loading, setLoading] = useState(!state?.courses);
const navigate = useNavigate(); const navigate = useNavigate();
useEffect(() => { useEffect(() => {
const fetchAllCourses = async () => { const fetchData = async () => {
if (!state?.courses) {
try { try {
const fetchedCourses = await fetchCourses(); // Fetch courses from API const academicYear = state?.academicYear;
setCourses(fetchedCourses); const [fetchedAppointments, fetchedCourses] = await Promise.all([
fetchAppointments(academicYear),
state?.courses ? Promise.resolve(state.courses) : fetchCourses(),
]);
setAppointments(fetchedAppointments);
if (!state?.courses) setCourses(fetchedCourses);
} catch (error) { } catch (error) {
console.error("Failed to fetch courses:", error); console.error("Failed to fetch data:", error);
} finally { } finally {
setLoading(false); setLoading(false);
} }
}
}; };
fetchAllCourses(); fetchData();
}, [state?.courses]); }, [state?.courses, state?.academicYear]);
useEffect(() => {
if (state?.updatedCourse) {
setCourses((prevCourses) =>
prevCourses.map((course) =>
course.courseId === state.updatedCourse.courseId
? { ...course, status: "Submitted" } // Update the status for the specific course
: course
)
);
}
}, [state?.updatedCourse]);
const getStatus = (courseId) => {
// Check if there's an appointment for the given courseId
return appointments.some((appointment) => appointment.courseId === courseId)
? "Submitted"
: "Not Submitted";
};
if (loading) { if (loading) {
return <div>Loading...</div>; return <div>Loading...</div>;
} }
const handleRowClick = (course) => { const handleRowClick = (course) => {
navigate(`/course-form/${course.courseId}`, { state: { course } }); navigate(`/course-form/${course.courseId}`, {
state: { course, academicYear: state?.academicYear },
});
}; };
return ( return (
<> <>
<Navbar/> <Navbar />
<table className="course-table"> <table className="course-table">
<thead> <thead>
<tr> <tr>
@@ -66,7 +65,7 @@ const CourseTable = () => {
<tr key={course.courseId} onClick={() => handleRowClick(course)}> <tr key={course.courseId} onClick={() => handleRowClick(course)}>
<td>{course.courseId}</td> <td>{course.courseId}</td>
<td>{course.name}</td> <td>{course.name}</td>
<td>{course.status}</td> <td>{getStatus(course.courseId)}</td>
</tr> </tr>
)) ))
) : ( ) : (

View File

@@ -5,11 +5,13 @@ import { fetchCourses } from "../api";
import Navbar from "./Navbar"; import Navbar from "./Navbar";
const FilterPage = () => { const FilterPage = () => {
const currentYear = new Date().getFullYear();
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
scheme: "", scheme: "",
semester: "", semester: "",
department: "", department: "",
program: "", program: "",
academicYear: `${currentYear}-${(currentYear + 1).toString().slice(-2)}`,
}); });
const navigate = useNavigate(); const navigate = useNavigate();
@@ -25,19 +27,32 @@ const FilterPage = () => {
}; };
const handleApplyFilter = async () => { const handleApplyFilter = async () => {
if (!formData.scheme || !formData.semester || !formData.department || !formData.program) { if (
!formData.scheme ||
!formData.semester ||
!formData.department ||
!formData.program ||
!formData.academicYear
) {
alert("Please fill all the fields before applying the filter."); alert("Please fill all the fields before applying the filter.");
return; return;
} }
try { try {
const filteredCourses = await fetchCourses(formData); const filteredCourses = await fetchCourses(formData);
console.log(formData);
if (filteredCourses.length > 0) { if (filteredCourses.length > 0) {
// Save filteredCourses in localStorage // Save filteredCourses in localStorage
localStorage.setItem("filteredCourses", JSON.stringify(filteredCourses)); localStorage.setItem(
"filteredCourses",
JSON.stringify(filteredCourses)
);
navigate("/courses", { state: { courses: filteredCourses } }); navigate("/courses", {
state: {
courses: filteredCourses,
academicYear: formData.academicYear,
},
});
} else { } else {
alert("No courses found for the selected filters."); alert("No courses found for the selected filters.");
} }
@@ -47,7 +62,6 @@ const FilterPage = () => {
} }
}; };
const getSemesters = () => { const getSemesters = () => {
if (!formData.program) return []; if (!formData.program) return [];
if (formData.program === "B.Tech") { if (formData.program === "B.Tech") {
@@ -59,9 +73,17 @@ const FilterPage = () => {
return []; return [];
}; };
const getAcademicYears = () => {
return Array.from({ length: 6 }, (_, i) => {
const startYear = currentYear - i;
const endYear = startYear + 1;
return `${startYear}-${endYear.toString().slice(-2)}`;
}); // Generate in YYYY-YY format
};
return ( return (
<> <>
<Navbar/> <Navbar />
<div className="filter-container"> <div className="filter-container">
<div className="filter-form"> <div className="filter-form">
<select <select
@@ -100,8 +122,20 @@ const FilterPage = () => {
onChange={handleInputChange} onChange={handleInputChange}
> >
<option value="">Select Scheme</option> <option value="">Select Scheme</option>
<option value="2020">SVU 2020</option> <option value="SVU 2020">SVU 2020</option>
<option value="2023">SVU 2023</option> <option value="SVU 2023">SVU 2023</option>
</select>
<select
name="academicYear"
value={formData.academicYear}
onChange={handleInputChange}
>
<option value="">Select Academic Year</option>
{getAcademicYears().map((year) => (
<option key={year} value={year}>
{year}
</option>
))}
</select> </select>
<button onClick={handleApplyFilter}>Apply Filter</button> <button onClick={handleApplyFilter}>Apply Filter</button>
</div> </div>

View File

@@ -5,20 +5,21 @@ import "./Navbar.css"; // Navbar-specific styles
const Navbar = () => { const Navbar = () => {
return ( return (
<header className="navbar mb-10"> <header className="navbar">
<div className="navbar-container"> <div className="navbar-container">
<NavLink to="/Welcom">
<FaUserCircle className="user-icon" /> <FaUserCircle className="user-icon" />
Appointment To Examiner
</NavLink>
<div className="button-container"> <div className="button-container">
<NavLink to="/consolidated" className="consolidated-button"> <NavLink to="/consolidated" className="consolidated-button">
Faculty Form Faculty Consolidated
</NavLink> </NavLink>
<NavLink to="/course-form" className="course-form-button"> <NavLink to="/courseConsolidated" className="consolidated-button">
Course Form Course Consolidated
</NavLink> </NavLink>
</div> </div>
<div> <div></div>
</div>
</div> </div>
</header> </header>
); );

View File

@@ -1,8 +1,8 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import axios from "axios"; import axios from "axios";
import * as XLSX from "xlsx-js-style";
import { jsPDF } from "jspdf"; import { jsPDF } from "jspdf";
import autoTable from "jspdf-autotable"; import autoTable from "jspdf-autotable";
import Navbar from "./Navbar";
const CourseConsolidated = () => { const CourseConsolidated = () => {
@@ -186,6 +186,8 @@ const CourseConsolidated = () => {
return ( return (
<>
<Navbar/>
<div> <div>
<h1 style={{ textAlign: "center" }}> <h1 style={{ textAlign: "center" }}>
Course Tables with Download Options Course Tables with Download Options
@@ -392,6 +394,7 @@ const CourseConsolidated = () => {
</button> </button>
</div> </div>
</div> </div>
</>
); );
}; };

View File

@@ -78,6 +78,18 @@ export const fetchOptions = async () => {
} }
}; };
export const fetchAppointments = async (academicYear) => {
try {
const response = await fetch(`${BASE_URL}/appointments?academicYear=${academicYear}`);
if (!response.ok) {
throw new Error("Failed to fetch appointments");
}
return await response.json();
} catch (error) {
console.error(error);
return [];
}
};
// Save multiple appointments to MongoDB // Save multiple appointments to MongoDB
export const saveAppointment = async (appointmentsData) => { export const saveAppointment = async (appointmentsData) => {

View File

@@ -8,7 +8,8 @@ const AppointmentSchema = new mongoose.Schema({
courseId: { type: String, required: true }, courseId: { type: String, required: true },
courseName: { type: String, required: true }, courseName: { type: String, required: true },
task: { type: String, required: true }, task: { type: String, required: true },
examPeriod: { type: String, required: true }, // New field for exam period examPeriod: { type: String, required: true },
academicYear: {type: String, required: true},
}); });
module.exports = mongoose.model("Appointment", AppointmentSchema); module.exports = mongoose.model("Appointment", AppointmentSchema);

View File

@@ -14,7 +14,7 @@ router.post("/", async (req, res) => {
const savedAppointments = []; const savedAppointments = [];
for (const appointment of appointments) { for (const appointment of appointments) {
const { facultyId, courseId, tasks, examPeriod } = appointment; const { facultyId, courseId, tasks, examPeriod, academicYear } = appointment;
if ( if (
!facultyId || !facultyId ||
@@ -43,6 +43,7 @@ router.post("/", async (req, res) => {
courseName: course.name, courseName: course.name,
task, task,
examPeriod, examPeriod,
academicYear,
}); });
const savedAppointment = await newAppointment.save(); const savedAppointment = await newAppointment.save();
savedAppointments.push(savedAppointment); savedAppointments.push(savedAppointment);
@@ -58,8 +59,9 @@ router.post("/", async (req, res) => {
// Get all appointments // Get all appointments
router.get("/", async (req, res) => { router.get("/", async (req, res) => {
const { academicYear } = req.query;
try { try {
const appointments = await Appointment.find(); const appointments = await Appointment.find({ academicYear });
res.json(appointments); res.json(appointments);
} catch (error) { } catch (error) {
console.error("Error fetching appointments:", error); console.error("Error fetching appointments:", error);