Fixed backend issue, update course status working

This commit is contained in:
Harshitha Shetty
2025-01-04 23:50:59 +05:30
parent b4adca13c7
commit 7079591f84
7 changed files with 123 additions and 454 deletions

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 } from "../api"; import { fetchFaculties, saveAppointment, updateCourseStatus } from "../api";
import "./CourseForm.css"; import "./CourseForm.css";
const CourseForm = () => { const CourseForm = () => {
@@ -85,7 +85,7 @@ const CourseForm = () => {
if (!groupedTasks[assignedFaculty.facultyId]) { if (!groupedTasks[assignedFaculty.facultyId]) {
groupedTasks[assignedFaculty.facultyId] = { groupedTasks[assignedFaculty.facultyId] = {
facultyId: assignedFaculty.facultyId, facultyId: assignedFaculty.facultyId,
courseId: course?.id || id, courseId: course?.courseId || id,
tasks: [], tasks: [],
}; };
} }
@@ -96,6 +96,7 @@ const CourseForm = () => {
const payload = Object.values(groupedTasks); // Convert the grouped tasks into an array const payload = Object.values(groupedTasks); // Convert the grouped tasks into an array
console.log("Saving appointment with payload:", payload); console.log("Saving appointment with payload:", payload);
await saveAppointment(payload); // Save to backend await saveAppointment(payload); // Save to backend
await updateCourseStatus(course?.courseId || id);
console.log("Form submitted successfully:", payload); console.log("Form submitted successfully:", payload);
// Redirect to courses page after successful submission // Redirect to courses page after successful submission
@@ -119,7 +120,7 @@ const CourseForm = () => {
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<label> <label>
Course ID: Course ID:
<input type="text" value={course?.id || id} readOnly /> <input type="text" value={course?.courseId || id} readOnly />
</label> </label>
<label> <label>
Course Name: Course Name:

View File

@@ -1,392 +0,0 @@
// import React, { useState, useEffect } from "react";
// import { useLocation, useParams, useNavigate } from "react-router-dom";
// import "./CourseForm.css";
// const CourseForm = () => {
// const { id } = useParams(); // Get the course ID from the URL params
// const location = useLocation();
// const navigate = useNavigate(); // Updated for navigation
// const { course } = location.state || {};
// const [options, setOptions] = useState({
// assessment: [],
// reassessment: [],
// paperSetting: [],
// moderation: [],
// pwdPaperSetter: [],
// oralsPracticals: [], // New field for Orals/Practicals
// });
// const [formData, setFormData] = useState({
// assessment: "",
// reassessment: "",
// paperSetting: "",
// moderation: "",
// pwdPaperSetter: "",
// oralsPracticals: "", // New field for Orals/Practicals
// });
// const [errors, setErrors] = useState({}); // To track validation errors
// // Fetch data for search bars
// useEffect(() => {
// const fetchOptions = async () => {
// try {
// const response = await fetch("/api/options"); // Replace with your API endpoint
// const data = await response.json();
// setOptions(data);
// } catch (error) {
// console.error("Failed to fetch options:", error);
// }
// };
// fetchOptions();
// }, []);
// const handleInputChange = (e) => {
// const { name, value } = e.target;
// setFormData({ ...formData, [name]: value });
// };
// const validateForm = () => {
// const newErrors = {};
// Object.keys(formData).forEach((field) => {
// if (!formData[field]) {
// newErrors[field] = "This field is required";
// }
// });
// setErrors(newErrors);
// return Object.keys(newErrors).length === 0;
// };
// const handleSubmit = (e) => {
// e.preventDefault();
// if (validateForm()) {
// console.log("Form submitted:", formData);
// navigate("/courses", { state: { updatedCourse: { ...course, status: "Submitted" } } });
// }
// };
// return (
// <div className="form-container">
// <h2>Course Info</h2>
// <form onSubmit={handleSubmit}>
// <label>
// Course ID:
// <input type="text" value={course?.id || id} readOnly />
// </label>
// <label>
// Course Name:
// <input type="text" value={course?.name || ""} readOnly />
// </label>
// <label className={errors.oralsPracticals ? "error" : ""}>
// Orals/Practicals:
// <input
// type="text"
// name="oralsPracticals"
// list="oralsPracticals-options"
// value={formData.oralsPracticals}
// onChange={handleInputChange}
// />
// <datalist id="oralsPracticals-options">
// {options.oralsPracticals.map((option, index) => (
// <option key={index} value={option} />
// ))}
// </datalist>
// {errors.oralsPracticals && <span className="error-message">{errors.oralsPracticals}</span>}
// </label>
// <label className={errors.assessment ? "error" : ""}>
// Assessment:
// <input
// type="text"
// name="assessment"
// list="assessment-options"
// value={formData.assessment}
// onChange={handleInputChange}
// />
// <datalist id="assessment-options">
// {options.assessment.map((option, index) => (
// <option key={index} value={option} />
// ))}
// </datalist>
// {errors.assessment && <span className="error-message">{errors.assessment}</span>}
// </label>
// <label className={errors.reassessment ? "error" : ""}>
// Reassessment:
// <input
// type="text"
// name="reassessment"
// list="reassessment-options"
// value={formData.reassessment}
// onChange={handleInputChange}
// />
// <datalist id="reassessment-options">
// {options.reassessment.map((option, index) => (
// <option key={index} value={option} />
// ))}
// </datalist>
// {errors.reassessment && <span className="error-message">{errors.reassessment}</span>}
// </label>
// <label className={errors.paperSetting ? "error" : ""}>
// Paper Setting:
// <input
// type="text"
// name="paperSetting"
// list="paperSetting-options"
// value={formData.paperSetting}
// onChange={handleInputChange}
// />
// <datalist id="paperSetting-options">
// {options.paperSetting.map((option, index) => (
// <option key={index} value={option} />
// ))}
// </datalist>
// {errors.paperSetting && <span className="error-message">{errors.paperSetting}</span>}
// </label>
// <label className={errors.moderation ? "error" : ""}>
// Moderation:
// <input
// type="text"
// name="moderation"
// list="moderation-options"
// value={formData.moderation}
// onChange={handleInputChange}
// />
// <datalist id="moderation-options">
// {options.moderation.map((option, index) => (
// <option key={index} value={option} />
// ))}
// </datalist>
// {errors.moderation && <span className="error-message">{errors.moderation}</span>}
// </label>
// <label className={errors.pwdPaperSetter ? "error" : ""}>
// PwD Paper Setter:
// <input
// type="text"
// name="pwdPaperSetter"
// list="pwdPaperSetter-options"
// value={formData.pwdPaperSetter}
// onChange={handleInputChange}
// />
// <datalist id="pwdPaperSetter-options">
// {options.pwdPaperSetter.map((option, index) => (
// <option key={index} value={option} />
// ))}
// </datalist>
// {errors.pwdPaperSetter && <span className="error-message">{errors.pwdPaperSetter}</span>}
// </label>
// <button type="submit" disabled={Object.keys(errors).length > 0}>Submit</button>
// </form>
// </div>
// );
// };
// export default CourseForm;
// CourseForm.jsx
import React, { useState, useEffect } from "react";
import { useLocation, useParams, useNavigate } from "react-router-dom";
import { fetchFaculties } from "../api";
import "./CourseForm.css";
const CourseForm = () => {
const { id } = useParams();
const location = useLocation();
const navigate = useNavigate();
const { course } = location.state || {};
const [options, setOptions] = useState({
assessment: [],
reassessment: [],
paperSetting: [],
moderation: [],
pwdPaperSetter: [],
oralsPracticals: [],
faculties: [], // New field for faculties
});
const [formData, setFormData] = useState({
assessment: "",
reassessment: "",
paperSetting: "",
moderation: "",
pwdPaperSetter: "",
oralsPracticals: "", // New field for Orals/Practicals
});
const [errors, setErrors] = useState({});
useEffect(() => {
const fetchOptionsAndFaculties = async () => {
try {
const facultiesData = await fetchFaculties(); // Fetch faculty names from the backend
console.log(facultiesData);
setOptions(prevOptions => ({
...prevOptions,
faculties: facultiesData,
}));
} catch (error) {
console.error("Failed to fetch faculties:", error);
}
};
fetchOptionsAndFaculties();
}, []);
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData({ ...formData, [name]: value });
};
const validateForm = () => {
const newErrors = {};
Object.keys(formData).forEach((field) => {
if (!formData[field]) {
newErrors[field] = "This field is required";
}
});
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
// const handleSubmit = (e) => {
// e.preventDefault();
// if (validateForm()) {
// console.log("Form submitted:", formData);
// navigate("/courses", { state: { updatedCourse: { ...course, status: "Submitted" } } });
// }
// };
const handleSubmit = (e) => {
e.preventDefault();
if (validateForm()) {
console.log("Form submitted:", formData);
navigate("/courses", {
state: {
updatedCourse: {
...course,
status: "Submitted", // Update status
...formData, // Include form data if required
},
},
});
}
};
return (
<div className="form-container">
<h2>Course Info</h2>
<form onSubmit={handleSubmit}>
<label>
Course ID:
<input type="text" value={course?.id || id} readOnly />
</label>
<label>
Course Name:
<input type="text" value={course?.name || ""} readOnly />
</label>
<label className={errors.oralsPracticals ? "error" : ""}>
Orals/Practicals:
<input
type="text"
name="oralsPracticals"
list="oralsPracticals-options"
value={formData.oralsPracticals}
onChange={handleInputChange}
/>
<datalist id="oralsPracticals-options">
{options.oralsPracticals.map((option, index) => (
<option key={index} value={option.name} />
))}
</datalist>
{errors.oralsPracticals && <span className="error-message">{errors.oralsPracticals}</span>}
</label>
<label className={errors.assessment ? "error" : ""}>
Assessment:
<input
type="text"
name="assessment"
list="assessment-options"
value={formData.assessment}
onChange={handleInputChange}
/>
<datalist id="assessment-options">
{options.assessment.map((option, index) => (
<option key={index} value={option.name} />
))}
</datalist>
{errors.assessment && <span className="error-message">{errors.assessment}</span>}
</label>
<label className={errors.reassessment ? "error" : ""}>
Reassessment:
<input
type="text"
name="reassessment"
list="reassessment-options"
value={formData.reassessment}
onChange={handleInputChange}
/>
<datalist id="reassessment-options">
{options.reassessment.map((option, index) => (
<option key={index} value={option.name} />
))}
</datalist>
{errors.reassessment && <span className="error-message">{errors.reassessment}</span>}
</label>
<label className={errors.paperSetting ? "error" : ""}>
Paper Setting:
<input
type="text"
name="paperSetting"
list="paperSetting-options"
value={formData.paperSetting}
onChange={handleInputChange}
/>
<datalist id="paperSetting-options">
{options.paperSetting.map((option, index) => (
<option key={index} value={option.name} />
))}
</datalist>
{errors.paperSetting && <span className="error-message">{errors.paperSetting}</span>}
</label>
<label className={errors.moderation ? "error" : ""}>
Moderation:
<input
type="text"
name="moderation"
list="moderation-options"
value={formData.moderation}
onChange={handleInputChange}
/>
<datalist id="moderation-options">
{options.moderation.map((option, index) => (
<option key={index} value={option.name} />
))}
</datalist>
{errors.moderation && <span className="error-message">{errors.moderation}</span>}
</label>
<label className={errors.pwdPaperSetter ? "error" : ""}>
PwD Paper Setter:
<input
type="text"
name="pwdPaperSetter"
list="pwdPaperSetter-options"
value={formData.pwdPaperSetter}
onChange={handleInputChange}
/>
<datalist id="pwdPaperSetter-options">
{options.pwdPaperSetter.map((option, index) => (
<option key={index} value={option.name} />
))}
</datalist>
{errors.pwdPaperSetter && <span className="error-message">{errors.pwdPaperSetter}</span>}
</label>
<button type="submit" disabled={Object.keys(errors).length > 0}>Submit</button>
</form>
</div>
);
};
export default CourseForm;

View File

@@ -1,52 +1,3 @@
// import React, { useState, useEffect } from 'react';
// import { useLocation, useNavigate } from "react-router-dom";
// import "./CourseTable.css";
// import { fetchCourses } from '../api';
// const CourseTable = () => {
// const { state } = useLocation();
// const courses = state?.courses;
// const navigate= useNavigate();
// console.log(courses);
// useEffect(() => {
// if (!courses || courses.length === 0) {
// alert("No courses available");
// }
// }, [courses]);
// if (!courses) {
// return <div>Loading...</div>;
// }
// const handleRowClick = (course) => {
// navigate(`/course-form/${course.courseId}`, { state: { course } });
// };
// return (
// <table className="course-table">
// <thead>
// <tr>
// <th>CourseID</th>
// <th>Course Name</th>
// <th>Status</th>
// </tr>
// </thead>
// <tbody>
// {courses.map(course => (
// <tr key={course.courseId} onClick={() => handleRowClick(course)}>
// <td>{course.courseId}</td>
// <td>{course.name}</td>
// <td>{course.status}</td>
// </tr>
// ))}
// </tbody>
// </table>
// );
// }
// export default CourseTable;
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";
@@ -75,23 +26,37 @@ const CourseTable = () => {
fetchAllCourses(); fetchAllCourses();
}, [state?.courses]); }, [state?.courses]);
// useEffect(() => {
// if (state?.updatedCourse) {
// setCourses((prevCourses) => {
// // Filter only the updated course
// const filteredCourses = prevCourses.filter((course) =>
// course.courseId === state.updatedCourse.courseId
// );
// return filteredCourses.map((course) =>
// course.courseId === state.updatedCourse.courseId
// ? { ...course, status: "Submitted" } // Update status
// : course
// );
// });
// }
// }, [state?.updatedCourse]);
useEffect(() => { useEffect(() => {
if (state?.updatedCourse) { if (state?.updatedCourse) {
setCourses((prevCourses) => { setCourses((prevCourses) =>
// Filter only the updated course prevCourses.map((course) =>
const filteredCourses = prevCourses.filter((course) =>
course.courseId === state.updatedCourse.courseId course.courseId === state.updatedCourse.courseId
); ? { ...course, status: "Submitted" } // Update the status for the specific course
return filteredCourses.map((course) =>
course.courseId === state.updatedCourse.courseId
? { ...course, status: "Submitted" } // Update status
: course : course
)
); );
});
} }
}, [state?.updatedCourse]); }, [state?.updatedCourse]);
if (loading) { if (loading) {
return <div>Loading...</div>; return <div>Loading...</div>;
} }

View File

@@ -120,3 +120,20 @@ export const saveAppointment = async (appointmentsData) => {
throw error; throw error;
} }
}; };
// Update course status
export const updateCourseStatus = async (courseId) => {
if (!courseId) {
throw new Error("Course ID is required to update the status");
}
const url = `${BASE_URL}/courses/${courseId}`;
return fetchData(url, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ status: "submitted" }), // Update status to "Submitted"
});
};

View File

@@ -1,6 +1,13 @@
const mongoose = require("mongoose"); const mongoose = require("mongoose");
const { v4: uuidv4 } = require("uuid");
const AppointmentSchema = new mongoose.Schema({ const AppointmentSchema = new mongoose.Schema({
appointmentId: {
type: String,
required: true,
unique: true,
default: uuidv4
},
facultyId: { type: String, required: true }, facultyId: { type: String, required: true },
facultyName: { type: String, required: true }, facultyName: { type: String, required: true },
courseId: { type: String, required: true }, courseId: { type: String, required: true },
@@ -9,3 +16,5 @@ const AppointmentSchema = new mongoose.Schema({
}); });
module.exports = mongoose.model("Appointment", AppointmentSchema); module.exports = mongoose.model("Appointment", AppointmentSchema);

View File

@@ -35,4 +35,39 @@ router.get("/:id", async (req, res) => {
} }
}); });
// Update course status route
router.patch("/api/courses/:courseId", async (req, res) => {
try {
const { courseId } = req.params; // Extract courseId from params
const { status } = req.body; // Extract status from body
console.log("Request params:", req.params);
console.log("Request body:", req.body);
// Validate status
if (!["submitted", "not submitted"].includes(status.toLowerCase())) {
return res.status(400).json({ message: "Invalid status value" });
}
// Find and update the course by courseId
const updatedCourse = await Course.findOneAndUpdate(
{ courseId }, // Query by courseId field
{ status: status.toLowerCase() }, // Set status (convert to lowercase)
{ new: true } // Return the updated document
);
if (!updatedCourse) {
console.error("Course not found:", courseId);
return res.status(404).json({ message: "Course not found" });
}
console.log("Updated course:", updatedCourse);
res.status(200).json(updatedCourse);
} catch (error) {
console.error("Error updating course status:", error.message);
res.status(500).json({ message: "Internal server error" });
}
});
module.exports = router; module.exports = router;

View File

@@ -14,6 +14,7 @@ const courseRoutes = require("./routes/courseRoutes");
const facultyRoutes = require("./routes/facultyRoutes"); const facultyRoutes = require("./routes/facultyRoutes");
const appointmentRoutes = require("./routes/appointmentRoutes"); const appointmentRoutes = require("./routes/appointmentRoutes");
const optionsRoutes = require("./routes/optionsRoutes"); const optionsRoutes = require("./routes/optionsRoutes");
const Course = require("./models/Course");
// MongoDB Connection // MongoDB Connection
mongoose mongoose
@@ -152,6 +153,39 @@ app.get("/api/user/profile", async (req, res) => {
} }
}); });
app.patch("/api/courses/:courseId", async (req, res) => {
const { courseId } = req.params;
const { status } = req.body;
console.log('Request params:', req.params);
console.log('Request body:', req.body);
if (!status) {
console.error("Status is missing in the request body.");
return res.status(400).json({ message: "Status is required" });
}
try {
const updatedCourse = await Course.findOneAndUpdate(
{ courseId: courseId }, // Use courseId field for finding the course
{ status }, // Update the status field
{ new: true }// Return the updated document
);
if (!updatedCourse) {
console.error("Course not found:", courseId);
return res.status(404).json({ message: "Course not found" });
}
res.json(updatedCourse);
} catch (error) {
console.error("Error updating course status:", error.message);
res.status(500).json({ message: "Internal server error" });
}
});
// Serve React Build Files // Serve React Build Files
app.use(express.static(path.join(__dirname, "../client/build"))); app.use(express.static(path.join(__dirname, "../client/build")));
app.get("*", (req, res) => app.get("*", (req, res) =>