added exam period in frontend and in database

This commit is contained in:
Harikrishnan Gopal
2025-01-24 19:28:52 +05:30
parent 675d5735b0
commit 2aa92edf9e
4 changed files with 110 additions and 70 deletions

View File

@@ -9,11 +9,8 @@ const CourseForm = () => {
const navigate = useNavigate();
const { course } = location.state || {};
const [options, setOptions] = useState({
faculties: [], // List of all faculties
});
const [suggestions, setSuggestions] = useState({}); // To hold suggestions for each field
const [options, setOptions] = useState({ faculties: [] });
const [suggestions, setSuggestions] = useState({});
const [formData, setFormData] = useState({
oralsPracticals: "",
assessment: "",
@@ -32,46 +29,38 @@ const CourseForm = () => {
pwdPaperSetter: [],
});
const [examPeriod, setExamPeriod] = useState({
year: "",
startMonth: "",
endMonth: "",
});
const [errors, setErrors] = useState({});
// Fetch faculty list on mount
useEffect(() => {
const fetchOptionsAndFaculties = async () => {
try {
const facultiesData = await fetchFaculties(); // Fetch faculty names from backend
const facultiesData = await fetchFaculties();
setOptions((prev) => ({ ...prev, faculties: facultiesData }));
} catch (error) {
console.error("Failed to fetch faculties:", error);
}
};
fetchOptionsAndFaculties();
}, []);
// Handle input changes for form fields
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
if (value.trim() === "") {
// Clear suggestions if input is empty
setSuggestions((prev) => ({
...prev,
[name]: [],
}));
setSuggestions((prev) => ({ ...prev, [name]: [] }));
return;
}
// Filter suggestions for the current field
if (options.faculties.length > 0) {
const filteredSuggestions = options.faculties.filter((faculty) =>
faculty.name.toLowerCase().includes(value.toLowerCase())
);
setSuggestions((prev) => ({
...prev,
[name]: filteredSuggestions,
}));
setSuggestions((prev) => ({ ...prev, [name]: filteredSuggestions }));
}
};
@@ -79,96 +68,75 @@ const CourseForm = () => {
const selectedFaculty = options.faculties.find(
(faculty) => faculty.name === formData[field]
);
if (selectedFaculty) {
setTempAssignments((prev) => ({
...prev,
[field]: [...prev[field], selectedFaculty],
}));
setFormData({ ...formData, [field]: "" }); // Clear input field
setSuggestions((prev) => ({ ...prev, [field]: [] })); // Clear suggestions
setFormData({ ...formData, [field]: "" });
setSuggestions((prev) => ({ ...prev, [field]: [] }));
}
};
const handleRemoveFaculty = (field, index) => {
setTempAssignments((prev) => {
const updatedAssignments = [...prev[field]]; // Create a shallow copy of the current list for this field
updatedAssignments.splice(index, 1); // Remove the faculty at the specified index
return { ...prev, [field]: updatedAssignments }; // Update the tempAssignments state
const updatedAssignments = [...prev[field]];
updatedAssignments.splice(index, 1);
return { ...prev, [field]: updatedAssignments };
});
};
const validateForm = () => {
const newErrors = {};
// Validate that each field in tempAssignments has at least one assigned faculty
Object.keys(tempAssignments).forEach((field) => {
if (!tempAssignments[field] || tempAssignments[field].length === 0) {
newErrors[field] = "At least one faculty must be assigned.";
}
});
if (!examPeriod.year || !examPeriod.startMonth || !examPeriod.endMonth) {
newErrors.examPeriod = "Exam period is required.";
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0; // Form is valid if no errors
return Object.keys(newErrors).length === 0;
};
// Handle form submission
const handleSubmit = async (e) => {
e.preventDefault(); // Prevent default form submission behavior
e.preventDefault();
// Validate the form based on tempAssignments
if (validateForm()) {
try {
const groupedTasks = {};
// Transform tempAssignments into grouped tasks by facultyId
Object.entries(tempAssignments).forEach(([field, facultyList]) => {
facultyList.forEach((faculty) => {
// Assuming faculty is an object, not just the faculty name
const assignedFaculty = options.faculties.find(
(optionFaculty) => optionFaculty.facultyId === faculty.facultyId
);
if (assignedFaculty) {
// Check if the facultyId already exists in groupedTasks
if (!groupedTasks[assignedFaculty.facultyId]) {
groupedTasks[assignedFaculty.facultyId] = {
facultyId: assignedFaculty.facultyId,
courseId: course?.courseId || id,
tasks: [],
examPeriod: `${examPeriod.year} (${examPeriod.startMonth} - ${examPeriod.endMonth})`,
};
}
// Push the task (field) into the tasks array for that faculty
groupedTasks[assignedFaculty.facultyId].tasks.push(field);
}
});
});
console.log(groupedTasks);
const payload = Object.values(groupedTasks); // Convert grouped tasks into an array
console.log("Saving appointment with payload:", payload);
if (payload.length === 0) {
throw new Error("No assignments to submit.");
}
// Call API to save appointments
const payload = Object.values(groupedTasks);
await saveAppointment(payload);
await updateCourseStatus(course?.courseId || id);
console.log("Form submitted successfully:", payload);
const filteredCourses =
JSON.parse(localStorage.getItem("filteredCourses")) || [];
// Redirect to courses page after successful submission
navigate("/courses", {
state: {
courses: filteredCourses,
updatedCourse: {
...course,
status: "Submitted",
},
updatedCourse: { ...course, status: "Submitted" },
},
});
} catch (error) {
@@ -227,7 +195,7 @@ const CourseForm = () => {
key={faculty.facultyId}
onClick={() => {
setFormData({ ...formData, [name]: faculty.name });
setSuggestions((prev) => ({ ...prev, [name]: [] })); // Clear suggestions for this field
setSuggestions((prev) => ({ ...prev, [name]: [] }));
}}
>
{faculty.name}
@@ -245,7 +213,7 @@ const CourseForm = () => {
onClick={() => handleRemoveFaculty(name, index)}
className="remove-faculty-btn"
>
✕ {/* This is the "X" symbol */}
✕
</button>
</li>
))}
@@ -256,6 +224,75 @@ const CourseForm = () => {
)}
</div>
))}
<div className={errors.examPeriod ? "error" : ""}>
<label>Exam Period:</label>
<select
value={examPeriod.year}
onChange={(e) => setExamPeriod({ ...examPeriod, year: e.target.value })}
>
<option value="">Year</option>
{[2025, 2026, 2027].map((year) => (
<option key={year} value={year}>
{year}
</option>
))}
</select>
<select
value={examPeriod.startMonth}
onChange={(e) =>
setExamPeriod({ ...examPeriod, startMonth: e.target.value })
}
>
<option value="">Start Month</option>
{[
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
].map((month) => (
<option key={month} value={month}>
{month}
</option>
))}
</select>
<select
value={examPeriod.endMonth}
onChange={(e) =>
setExamPeriod({ ...examPeriod, endMonth: e.target.value })
}
>
<option value="">End Month</option>
{[
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
].map((month) => (
<option key={month} value={month}>
{month}
</option>
))}
</select>
{errors.examPeriod && (
<span className="error-message">{errors.examPeriod}</span>
)}
</div>
<button type="submit">Submit</button>
</form>
</div>

View File

@@ -78,6 +78,7 @@ export const fetchOptions = async () => {
}
};
// Save multiple appointments to MongoDB
export const saveAppointment = async (appointmentsData) => {
console.log("Saving appointments with payload:", appointmentsData);

View File

@@ -2,19 +2,16 @@ const mongoose = require("mongoose");
const { v4: uuidv4 } = require("uuid");
const AppointmentSchema = new mongoose.Schema({
appointmentId: {
type: String,
required: true,
unique: true,
default: uuidv4
},
appointmentId: { type: String, required: true, unique: true, default: uuidv4 },
facultyId: { type: String, required: true },
facultyName: { type: String, required: true },
courseId: { type: String, required: true },
courseName: { type: String, required: true },
task: { type: String, required: true },
examPeriod: { type: String, required: true }, // New field for exam period
});
module.exports = mongoose.model("Appointment", AppointmentSchema);

View File

@@ -7,17 +7,22 @@ const Course = require("../models/Course");
// Save multiple appointments
router.post("/", async (req, res) => {
try {
const { appointments } = req.body; // Expecting an array of appointments
const { appointments } = req.body;
if (!appointments || !Array.isArray(appointments)) {
return res.status(400).json({ error: "Invalid or missing data" });
}
const savedAppointments = [];
for (const appointment of appointments) {
const { facultyId, courseId, tasks } = appointment;
const { facultyId, courseId, tasks, examPeriod } = appointment;
// Validate input data
if (!facultyId || !courseId || !Array.isArray(tasks) || tasks.length === 0) {
if (
!facultyId ||
!courseId ||
!Array.isArray(tasks) ||
tasks.length === 0 ||
!examPeriod
) {
return res.status(400).json({ error: "Invalid appointment data" });
}
@@ -30,7 +35,6 @@ router.post("/", async (req, res) => {
});
}
// Save each task as a separate appointment
for (const task of tasks) {
const newAppointment = new Appointment({
facultyId,
@@ -38,6 +42,7 @@ router.post("/", async (req, res) => {
courseId,
courseName: course.name,
task,
examPeriod,
});
const savedAppointment = await newAppointment.save();
savedAppointments.push(savedAppointment);