diff --git a/src/main/java/org/example/se302/controller/ScheduleCalendarController.java b/src/main/java/org/example/se302/controller/ScheduleCalendarController.java index 550cc86..c4c333e 100644 --- a/src/main/java/org/example/se302/controller/ScheduleCalendarController.java +++ b/src/main/java/org/example/se302/controller/ScheduleCalendarController.java @@ -745,4 +745,68 @@ public class ScheduleCalendarController { "Could not update the exam assignment. The exam may be locked."); } } + + /** + * Exports the schedule as a CSV grid (days × time slots). + */ + @FXML + private void onExportCSV() { + if (currentSchedule == null || currentConfig == null) { + showAlert(Alert.AlertType.WARNING, "No Schedule", + "Please generate a schedule first."); + return; + } + + javafx.stage.FileChooser fileChooser = new javafx.stage.FileChooser(); + fileChooser.setTitle("Export Schedule as CSV"); + fileChooser.getExtensionFilters().add( + new javafx.stage.FileChooser.ExtensionFilter("CSV Files", "*.csv")); + fileChooser.setInitialFileName("schedule_calendar.csv"); + + java.io.File file = fileChooser.showSaveDialog(scheduleGrid.getScene().getWindow()); + if (file == null) + return; + + try (java.io.PrintWriter writer = new java.io.PrintWriter(file)) { + int numDays = currentConfig.getNumDays(); + int slotsPerDay = currentConfig.getSlotsPerDay(); + + // Header row: Time Slot, Day 1, Day 2, ... + StringBuilder header = new StringBuilder("Time Slot"); + for (int day = 0; day < numDays; day++) { + LocalDate date = currentConfig.getStartDate().plusDays(day); + header.append(",").append(date.toString()); + } + writer.println(header); + + // Data rows: one per time slot + for (int slot = 0; slot < slotsPerDay; slot++) { + StringBuilder row = new StringBuilder(); + TimeSlot timeSlot = currentConfig.getTimeSlot(0, slot); + String slotLabel = timeSlot != null + ? timeSlot.getStartTime() + "-" + timeSlot.getEndTime() + : "Slot " + (slot + 1); + row.append(slotLabel); + + for (int day = 0; day < numDays; day++) { + row.append(","); + // Find exams at this day/slot + List exams = new ArrayList<>(); + for (ExamAssignment a : currentSchedule.getAssignments().values()) { + if (a.isAssigned() && a.getDay() == day && a.getTimeSlotIndex() == slot) { + exams.add(a.getCourseCode() + " (" + a.getClassroomId() + ")"); + } + } + row.append("\"").append(String.join("; ", exams)).append("\""); + } + writer.println(row); + } + + showAlert(Alert.AlertType.INFORMATION, "Export Complete", + "Schedule exported to:\n" + file.getAbsolutePath()); + } catch (java.io.IOException e) { + showAlert(Alert.AlertType.ERROR, "Export Failed", + "Could not write file: " + e.getMessage()); + } + } } diff --git a/src/main/java/org/example/se302/controller/ScheduleClassroomController.java b/src/main/java/org/example/se302/controller/ScheduleClassroomController.java index 330645f..1113655 100644 --- a/src/main/java/org/example/se302/controller/ScheduleClassroomController.java +++ b/src/main/java/org/example/se302/controller/ScheduleClassroomController.java @@ -265,4 +265,62 @@ public class ScheduleClassroomController { return slotIndex; } } + + /** + * Exports the selected classroom's schedule as CSV. + */ + @FXML + private void onExportCSV() { + Classroom selected = classroomComboBox.getValue(); + if (selected == null) { + showAlert(javafx.scene.control.Alert.AlertType.WARNING, "No Classroom", + "Please select a classroom first."); + return; + } + + if (scheduleTable.getItems().isEmpty()) { + showAlert(javafx.scene.control.Alert.AlertType.WARNING, "No Data", + "No schedule data to export."); + return; + } + + javafx.stage.FileChooser fileChooser = new javafx.stage.FileChooser(); + fileChooser.setTitle("Export Classroom Schedule as CSV"); + fileChooser.getExtensionFilters().add( + new javafx.stage.FileChooser.ExtensionFilter("CSV Files", "*.csv")); + fileChooser.setInitialFileName("schedule_classroom_" + selected.getClassroomId() + ".csv"); + + java.io.File file = fileChooser.showSaveDialog(scheduleTable.getScene().getWindow()); + if (file == null) + return; + + try (java.io.PrintWriter writer = new java.io.PrintWriter(file)) { + // Header + writer.println("Classroom,Date,Time,Course,Students"); + + // Data rows + for (ClassroomSlotEntry entry : scheduleTable.getItems()) { + writer.println(String.format("%s,\"%s\",%s,%s,%d", + selected.getClassroomId(), + entry.getDate(), + entry.getTime(), + entry.getCourse(), + entry.getStudentCount())); + } + + showAlert(javafx.scene.control.Alert.AlertType.INFORMATION, "Export Complete", + "Classroom schedule exported to:\n" + file.getAbsolutePath()); + } catch (java.io.IOException e) { + showAlert(javafx.scene.control.Alert.AlertType.ERROR, "Export Failed", + "Could not write file: " + e.getMessage()); + } + } + + private void showAlert(javafx.scene.control.Alert.AlertType type, String title, String message) { + javafx.scene.control.Alert alert = new javafx.scene.control.Alert(type); + alert.setTitle(title); + alert.setHeaderText(null); + alert.setContentText(message); + alert.showAndWait(); + } } diff --git a/src/main/java/org/example/se302/controller/ScheduleCourseController.java b/src/main/java/org/example/se302/controller/ScheduleCourseController.java index e50c8ca..4c85063 100644 --- a/src/main/java/org/example/se302/controller/ScheduleCourseController.java +++ b/src/main/java/org/example/se302/controller/ScheduleCourseController.java @@ -236,4 +236,55 @@ public class ScheduleCourseController { return slotIndex; } } + + /** + * Exports the course schedule as a CSV file. + */ + @FXML + private void onExportCSV() { + if (courseScheduleTable.getItems().isEmpty()) { + showAlert(javafx.scene.control.Alert.AlertType.WARNING, "No Data", + "No schedule data to export."); + return; + } + + javafx.stage.FileChooser fileChooser = new javafx.stage.FileChooser(); + fileChooser.setTitle("Export Course Schedule as CSV"); + fileChooser.getExtensionFilters().add( + new javafx.stage.FileChooser.ExtensionFilter("CSV Files", "*.csv")); + fileChooser.setInitialFileName("schedule_courses.csv"); + + java.io.File file = fileChooser.showSaveDialog(courseScheduleTable.getScene().getWindow()); + if (file == null) + return; + + try (java.io.PrintWriter writer = new java.io.PrintWriter(file)) { + // Header + writer.println("Course Code,Date,Time,Classroom,Enrolled Students"); + + // Data rows + for (CourseScheduleEntry entry : courseScheduleTable.getItems()) { + writer.println(String.format("%s,\"%s\",%s,%s,%d", + entry.getCourseCode(), + entry.getDate(), + entry.getTime(), + entry.getClassroom(), + entry.getEnrolledCount())); + } + + showAlert(javafx.scene.control.Alert.AlertType.INFORMATION, "Export Complete", + "Course schedule exported to:\n" + file.getAbsolutePath()); + } catch (java.io.IOException e) { + showAlert(javafx.scene.control.Alert.AlertType.ERROR, "Export Failed", + "Could not write file: " + e.getMessage()); + } + } + + private void showAlert(javafx.scene.control.Alert.AlertType type, String title, String message) { + javafx.scene.control.Alert alert = new javafx.scene.control.Alert(type); + alert.setTitle(title); + alert.setHeaderText(null); + alert.setContentText(message); + alert.showAndWait(); + } } diff --git a/src/main/java/org/example/se302/controller/ScheduleStudentController.java b/src/main/java/org/example/se302/controller/ScheduleStudentController.java index 00b646d..de3a6df 100644 --- a/src/main/java/org/example/se302/controller/ScheduleStudentController.java +++ b/src/main/java/org/example/se302/controller/ScheduleStudentController.java @@ -230,4 +230,62 @@ public class ScheduleStudentController { return slotIndex; } } + + /** + * Exports the selected student's schedule as CSV. + */ + @FXML + private void onExportCSV() { + Student selected = studentComboBox.getValue(); + if (selected == null) { + showAlert(Alert.AlertType.WARNING, "No Student", + "Please select a student first."); + return; + } + + if (scheduleTable.getItems().isEmpty()) { + showAlert(Alert.AlertType.WARNING, "No Data", + "No schedule data to export."); + return; + } + + javafx.stage.FileChooser fileChooser = new javafx.stage.FileChooser(); + fileChooser.setTitle("Export Student Schedule as CSV"); + fileChooser.getExtensionFilters().add( + new javafx.stage.FileChooser.ExtensionFilter("CSV Files", "*.csv")); + fileChooser.setInitialFileName("schedule_student_" + selected.getStudentId() + ".csv"); + + java.io.File file = fileChooser.showSaveDialog(scheduleTable.getScene().getWindow()); + if (file == null) + return; + + try (java.io.PrintWriter writer = new java.io.PrintWriter(file)) { + // Header + writer.println("Student ID,Course,Date,Time,Classroom"); + + // Data rows + for (CourseScheduleEntry entry : scheduleTable.getItems()) { + writer.println(String.format("%s,%s,\"%s\",%s,%s", + selected.getStudentId(), + entry.getCourseCode(), + entry.getDateDisplay(), + entry.getTimeDisplay(), + entry.getClassroom())); + } + + showAlert(Alert.AlertType.INFORMATION, "Export Complete", + "Student schedule exported to:\n" + file.getAbsolutePath()); + } catch (java.io.IOException e) { + showAlert(Alert.AlertType.ERROR, "Export Failed", + "Could not write file: " + e.getMessage()); + } + } + + private void showAlert(Alert.AlertType type, String title, String message) { + Alert alert = new Alert(type); + alert.setTitle(title); + alert.setHeaderText(null); + alert.setContentText(message); + alert.showAndWait(); + } } diff --git a/src/main/resources/org/example/se302/view/schedule-calendar-view.fxml b/src/main/resources/org/example/se302/view/schedule-calendar-view.fxml index 1957d14..f365751 100644 --- a/src/main/resources/org/example/se302/view/schedule-calendar-view.fxml +++ b/src/main/resources/org/example/se302/view/schedule-calendar-view.fxml @@ -123,7 +123,7 @@