academicYear logic
This commit is contained in:
@@ -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 (
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -1,52 +1,51 @@
|
|||||||
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 (
|
||||||
@@ -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>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
|
|||||||
@@ -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,6 +73,14 @@ 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 />
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -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>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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) => {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user