diff --git a/src/main/java/org/example/se302/controller/ExamEditDialog.java b/src/main/java/org/example/se302/controller/ExamEditDialog.java index 3334921..6cc451d 100644 --- a/src/main/java/org/example/se302/controller/ExamEditDialog.java +++ b/src/main/java/org/example/se302/controller/ExamEditDialog.java @@ -236,13 +236,13 @@ public class ExamEditDialog extends Dialog { validationPanel.setStyle("-fx-background-color: #e8f5e9; -fx-background-radius: 5;"); updateButtonStates(true, false); } else if (currentValidation.hasHardViolations()) { - validationStatusLabel.setText("❌ Constraint violations found"); + validationStatusLabel.setText("Constraint violations found!"); validationStatusLabel.setTextFill(Color.web("#e74c3c")); violationDetails.setText(currentValidation.getFormattedMessage()); validationPanel.setStyle("-fx-background-color: #ffebee; -fx-background-radius: 5;"); updateButtonStates(false, true); } else { - validationStatusLabel.setText("⚠️ Warnings found"); + validationStatusLabel.setText("Warnings found!"); validationStatusLabel.setTextFill(Color.web("#f39c12")); violationDetails.setText(currentValidation.getFormattedMessage()); validationPanel.setStyle("-fx-background-color: #fff3e0; -fx-background-radius: 5;"); diff --git a/src/main/java/org/example/se302/controller/ScheduleClassroomController.java b/src/main/java/org/example/se302/controller/ScheduleClassroomController.java index b0a9a58..330645f 100644 --- a/src/main/java/org/example/se302/controller/ScheduleClassroomController.java +++ b/src/main/java/org/example/se302/controller/ScheduleClassroomController.java @@ -11,14 +11,13 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import org.example.se302.model.Classroom; -import org.example.se302.model.ExamAssignment; +import org.example.se302.model.Course; import org.example.se302.model.ScheduleConfiguration; import org.example.se302.service.DataManager; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Comparator; -import java.util.Map; /** * Controller for the Classroom Schedule view. @@ -47,10 +46,6 @@ public class ScheduleClassroomController { private DataManager dataManager; - // Reference to the current schedule state (set by parent controller) - private Map currentAssignments; - private ScheduleConfiguration configuration; - @FXML public void initialize() { dataManager = DataManager.getInstance(); @@ -112,15 +107,35 @@ public class ScheduleClassroomController { } } }); - } - /** - * Sets the current schedule assignments. Called by parent controller after - * schedule generation. - */ - public void setScheduleData(Map assignments, ScheduleConfiguration config) { - this.currentAssignments = assignments; - this.configuration = config; + // Refresh when tab is selected - find TabPane once scene is available + scheduleTable.sceneProperty().addListener((obs, oldScene, newScene) -> { + if (newScene != null) { + // Find parent TabPane and listen for selection changes + javafx.scene.Parent parent = scheduleTable.getParent(); + while (parent != null) { + if (parent.getParent() instanceof javafx.scene.control.TabPane) { + javafx.scene.control.TabPane tabPane = (javafx.scene.control.TabPane) parent + .getParent(); + // Find which tab contains our content + for (javafx.scene.control.Tab tab : tabPane.getTabs()) { + if (tab.getContent() == parent) { + tab.selectedProperty().addListener( + (o, wasSelected, isSelected) -> { + if (isSelected && classroomComboBox + .getValue() != null) { + onShowSchedule(); + } + }); + break; + } + } + break; + } + parent = parent.getParent(); + } + } + }); } @FXML @@ -132,52 +147,52 @@ public class ScheduleClassroomController { selectedClassroomLabel.setText("Schedule for: " + selected.getClassroomId() + " (Capacity: " + selected.getCapacity() + ")"); + ScheduleConfiguration config = dataManager.getActiveConfiguration(); ObservableList entries = FXCollections.observableArrayList(); int totalSlots = 0; int usedSlots = 0; int totalStudents = 0; - // If we have assignments, filter by this classroom - if (currentAssignments != null && !currentAssignments.isEmpty()) { - for (ExamAssignment assignment : currentAssignments.values()) { - if (assignment.isAssigned() && - selected.getClassroomId().equals(assignment.getClassroomId())) { + // Find all courses scheduled in this classroom + for (Course course : dataManager.getCourses()) { + if (course.isScheduled() && + selected.getClassroomId().equals(course.getAssignedClassroom())) { - // Format date - String dateStr; - if (configuration != null && configuration.getStartDate() != null) { - LocalDate examDate = configuration.getStartDate() - .plusDays(assignment.getDay()); - dateStr = examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")); - } else { - dateStr = "Day " + (assignment.getDay() + 1); - } + int dayIndex = course.getExamDay(); + int slotIndex = course.getExamTimeSlot(); - // Format time - String timeStr = "Slot " + (assignment.getTimeSlotIndex() + 1); - - // Calculate utilization percentage for this slot - int studentCount = assignment.getStudentCount(); - int capacity = selected.getCapacity(); - int utilizationPercent = capacity > 0 ? (studentCount * 100) / capacity : 0; - String utilizationStr = utilizationPercent + "%"; - - entries.add(new ClassroomSlotEntry( - dateStr, timeStr, assignment.getCourseCode(), - studentCount, utilizationStr, utilizationPercent, - assignment.getDay(), assignment.getTimeSlotIndex())); - - usedSlots++; - totalStudents += studentCount; + // Format date + String dateStr; + if (config != null && config.getStartDate() != null) { + LocalDate examDate = config.getStartDate().plusDays(dayIndex); + dateStr = examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")); + } else { + dateStr = "Day " + (dayIndex + 1); } - } - // Calculate total possible slots - if (configuration != null) { - totalSlots = configuration.getNumDays() * configuration.getSlotsPerDay(); + String timeStr = "Slot " + (slotIndex + 1); + + // Calculate utilization + int studentCount = course.getEnrolledStudentsCount(); + int capacity = selected.getCapacity(); + int utilizationPercent = capacity > 0 ? (studentCount * 100) / capacity : 0; + String utilizationStr = utilizationPercent + "%"; + + entries.add(new ClassroomSlotEntry( + dateStr, timeStr, course.getCourseCode(), + studentCount, utilizationStr, utilizationPercent, + dayIndex, slotIndex)); + + usedSlots++; + totalStudents += studentCount; } } + // Calculate total possible slots + if (config != null) { + totalSlots = config.getNumDays() * config.getSlotsPerDay(); + } + // Sort by day then slot entries.sort(Comparator.comparingInt(ClassroomSlotEntry::getDayIndex) .thenComparingInt(ClassroomSlotEntry::getSlotIndex)); diff --git a/src/main/java/org/example/se302/controller/ScheduleCourseController.java b/src/main/java/org/example/se302/controller/ScheduleCourseController.java index bae7a9a..e50c8ca 100644 --- a/src/main/java/org/example/se302/controller/ScheduleCourseController.java +++ b/src/main/java/org/example/se302/controller/ScheduleCourseController.java @@ -9,14 +9,12 @@ import javafx.scene.control.TableColumn; import javafx.scene.control.TableRow; import javafx.scene.control.TableView; import org.example.se302.model.Course; -import org.example.se302.model.ExamAssignment; import org.example.se302.model.ScheduleConfiguration; import org.example.se302.service.DataManager; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.Comparator; -import java.util.Map; // Color palette for days (pastel colors for readability) // Day 0 = Light Blue, Day 1 = Light Green, Day 2 = Light Yellow, etc. @@ -43,11 +41,6 @@ public class ScheduleCourseController { private DataManager dataManager; - // Reference to the current schedule state (set by parent controller or loaded - // from DB) - private Map currentAssignments; - private ScheduleConfiguration configuration; - @FXML public void initialize() { dataManager = DataManager.getInstance(); @@ -122,19 +115,38 @@ public class ScheduleCourseController { // Listen for data changes dataManager.getCourses().addListener( (javafx.collections.ListChangeListener) c -> loadScheduleData()); - } - /** - * Sets the current schedule assignments. Called by parent controller after - * schedule generation. - */ - public void setScheduleData(Map assignments, ScheduleConfiguration config) { - this.currentAssignments = assignments; - this.configuration = config; - loadScheduleData(); + // Refresh when tab is selected - find TabPane once scene is available + courseScheduleTable.sceneProperty().addListener((obs, oldScene, newScene) -> { + if (newScene != null) { + loadScheduleData(); + // Find parent TabPane and listen for selection changes + javafx.scene.Parent parent = courseScheduleTable.getParent(); + while (parent != null) { + if (parent.getParent() instanceof javafx.scene.control.TabPane) { + javafx.scene.control.TabPane tabPane = (javafx.scene.control.TabPane) parent + .getParent(); + // Find which tab contains our content + for (javafx.scene.control.Tab tab : tabPane.getTabs()) { + if (tab.getContent() == parent) { + tab.selectedProperty().addListener( + (o, wasSelected, isSelected) -> { + if (isSelected) + loadScheduleData(); + }); + break; + } + } + break; + } + parent = parent.getParent(); + } + } + }); } private void loadScheduleData() { + ScheduleConfiguration config = dataManager.getActiveConfiguration(); ObservableList entries = FXCollections.observableArrayList(); for (Course course : dataManager.getCourses()) { @@ -144,33 +156,24 @@ public class ScheduleCourseController { String dateStr = "Not Scheduled"; String timeStr = "-"; String classroomStr = "-"; - int dayIndex = Integer.MAX_VALUE; // For sorting unscheduled items last + int dayIndex = Integer.MAX_VALUE; int slotIndex = Integer.MAX_VALUE; - // Check if we have an assignment for this course - if (currentAssignments != null && currentAssignments.containsKey(courseCode)) { - ExamAssignment assignment = currentAssignments.get(courseCode); + // Check if this course has been scheduled + if (course.isScheduled()) { + dayIndex = course.getExamDay(); + slotIndex = course.getExamTimeSlot(); + classroomStr = course.getAssignedClassroom(); - if (assignment.isAssigned()) { - dayIndex = assignment.getDay(); - slotIndex = assignment.getTimeSlotIndex(); - - // Format date based on configuration start date + day offset - if (configuration != null && configuration.getStartDate() != null) { - LocalDate examDate = configuration.getStartDate().plusDays(dayIndex); - dateStr = examDate.format( - DateTimeFormatter.ofPattern("dd/MM/yyyy (EEEE)")); - } else { - dateStr = "Day " + (dayIndex + 1); - } - - // Format time slot - timeStr = "Slot " + (slotIndex + 1); - - // Classroom - classroomStr = assignment.getClassroomId() != null ? assignment.getClassroomId() - : "-"; + // Format date using configuration's start date + if (config != null && config.getStartDate() != null) { + LocalDate examDate = config.getStartDate().plusDays(dayIndex); + dateStr = examDate.format(DateTimeFormatter.ofPattern("dd/MM/yyyy (EEEE)")); + } else { + dateStr = "Day " + (dayIndex + 1); } + + timeStr = "Slot " + (slotIndex + 1); } entries.add(new CourseScheduleEntry(courseCode, enrolled, dateStr, timeStr, classroomStr,