Implement initial application UI including schedule generation and import views, a main controller, and update Maven compiler

This commit is contained in:
feyzagereme
2025-12-17 19:16:43 +03:00
parent cbf1d0b13c
commit ce556e92fd
6 changed files with 702 additions and 324 deletions

View File

@@ -9,71 +9,108 @@
fx:controller="org.example.se302.controller.ImportController"
fitToWidth="true" fitToHeight="true"
hbarPolicy="AS_NEEDED" vbarPolicy="AS_NEEDED">
<VBox spacing="20" styleClass="content-pane">
<VBox spacing="24" styleClass="content-pane">
<padding>
<Insets top="20" right="20" bottom="20" left="20"/>
<Insets top="40" right="40" bottom="40" left="40"/>
</padding>
<!-- Header -->
<Label text="Import Data from CSV Files" styleClass="section-title"/>
<Label text="Select CSV files to import student, course, classroom, and enrollment data." wrapText="true"/>
<Separator/>
<!-- Students Import Section -->
<VBox spacing="8">
<Label text="Student Data" styleClass="subsection-title"/>
<HBox spacing="10" alignment="CENTER_LEFT">
<TextField fx:id="studentFileField" promptText="No file selected" editable="false" HBox.hgrow="ALWAYS"/>
<Button fx:id="studentBrowseButton" text="Browse..." onAction="#onBrowseStudents"/>
</HBox>
<Label fx:id="studentStatusLabel" text="Not Loaded" styleClass="status-label"/>
</VBox>
<!-- Courses Import Section -->
<VBox spacing="8">
<Label text="Course Data" styleClass="subsection-title"/>
<HBox spacing="10" alignment="CENTER_LEFT">
<TextField fx:id="courseFileField" promptText="No file selected" editable="false" HBox.hgrow="ALWAYS"/>
<Button fx:id="courseBrowseButton" text="Browse..." onAction="#onBrowseCourses"/>
</HBox>
<Label fx:id="courseStatusLabel" text="Not Loaded" styleClass="status-label"/>
</VBox>
<!-- Classrooms Import Section -->
<VBox spacing="8">
<Label text="Classroom Data" styleClass="subsection-title"/>
<HBox spacing="10" alignment="CENTER_LEFT">
<TextField fx:id="classroomFileField" promptText="No file selected" editable="false" HBox.hgrow="ALWAYS"/>
<Button fx:id="classroomBrowseButton" text="Browse..." onAction="#onBrowseClassrooms"/>
</HBox>
<Label fx:id="classroomStatusLabel" text="Not Loaded" styleClass="status-label"/>
</VBox>
<!-- Enrollments Import Section -->
<VBox spacing="8">
<Label text="Enrollment Data" styleClass="subsection-title"/>
<HBox spacing="10" alignment="CENTER_LEFT">
<TextField fx:id="enrollmentFileField" promptText="No file selected" editable="false" HBox.hgrow="ALWAYS"/>
<Button fx:id="enrollmentBrowseButton" text="Browse..." onAction="#onBrowseEnrollments"/>
</HBox>
<Label fx:id="enrollmentStatusLabel" text="Not Loaded" styleClass="status-label"/>
<Label text="📁 Data Integration" styleClass="section-title"/>
<Label text="Upload CSV files to initialize the exam scheduling process."
styleClass="description-label" wrapText="true"/>
</VBox>
<Separator/>
<!-- Import Messages Area -->
<VBox spacing="5" VBox.vgrow="ALWAYS">
<!-- Import Cards Grid -->
<GridPane hgap="24" vgap="24">
<columnConstraints>
<ColumnConstraints percentWidth="50" hgrow="ALWAYS"/>
<ColumnConstraints percentWidth="50" hgrow="ALWAYS"/>
</columnConstraints>
<!-- Student Data Card -->
<VBox spacing="16" styleClass="card" GridPane.columnIndex="0" GridPane.rowIndex="0">
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="👤" style="-fx-font-size: 32px;"/>
<VBox>
<Label text="Student Data" styleClass="subsection-title"/>
<Label text="students.csv" styleClass="status-label"/>
</VBox>
<Region HBox.hgrow="ALWAYS"/>
<Button fx:id="studentBrowseButton" text="Browse..." onAction="#onBrowseStudents"
styleClass="secondary-button, small-button"/>
</HBox>
<TextField fx:id="studentFileField" promptText="No file selected" editable="false"/>
<Label fx:id="studentStatusLabel" text="Not Loaded" styleClass="status-label"/>
</VBox>
<!-- Course Data Card -->
<VBox spacing="16" styleClass="card" GridPane.columnIndex="1" GridPane.rowIndex="0">
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="📚" style="-fx-font-size: 32px;"/>
<VBox>
<Label text="Course Data" styleClass="subsection-title"/>
<Label text="courses.csv" styleClass="status-label"/>
</VBox>
<Region HBox.hgrow="ALWAYS"/>
<Button fx:id="courseBrowseButton" text="Browse..." onAction="#onBrowseCourses"
styleClass="secondary-button, small-button"/>
</HBox>
<TextField fx:id="courseFileField" promptText="No file selected" editable="false"/>
<Label fx:id="courseStatusLabel" text="Not Loaded" styleClass="status-label"/>
</VBox>
<!-- Classroom Data Card -->
<VBox spacing="16" styleClass="card" GridPane.columnIndex="0" GridPane.rowIndex="1">
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="🏛️" style="-fx-font-size: 32px;"/>
<VBox>
<Label text="Classroom Data" styleClass="subsection-title"/>
<Label text="classrooms.csv" styleClass="status-label"/>
</VBox>
<Region HBox.hgrow="ALWAYS"/>
<Button fx:id="classroomBrowseButton" text="Browse..." onAction="#onBrowseClassrooms"
styleClass="secondary-button, small-button"/>
</HBox>
<TextField fx:id="classroomFileField" promptText="No file selected" editable="false"/>
<Label fx:id="classroomStatusLabel" text="Not Loaded" styleClass="status-label"/>
</VBox>
<!-- Enrollment Data Card -->
<VBox spacing="16" styleClass="card" GridPane.columnIndex="1" GridPane.rowIndex="1">
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="📝" style="-fx-font-size: 32px;"/>
<VBox>
<Label text="Enrollment Data" styleClass="subsection-title"/>
<Label text="enrollments.csv" styleClass="status-label"/>
</VBox>
<Region HBox.hgrow="ALWAYS"/>
<Button fx:id="enrollmentBrowseButton" text="Browse..." onAction="#onBrowseEnrollments"
styleClass="secondary-button, small-button"/>
</HBox>
<TextField fx:id="enrollmentFileField" promptText="No file selected" editable="false"/>
<Label fx:id="enrollmentStatusLabel" text="Not Loaded" styleClass="status-label"/>
</VBox>
</GridPane>
<Separator/>
<!-- Import Log -->
<VBox spacing="12" VBox.vgrow="ALWAYS" styleClass="card">
<Label text="Import Messages" styleClass="subsection-title"/>
<TextArea fx:id="messagesArea" editable="false" wrapText="true" VBox.vgrow="ALWAYS"
promptText="Validation messages and import results will appear here..."/>
prefHeight="200"
promptText="Validation messages and import results will appear here..."
style="-fx-font-family: 'Consolas', 'Monaco', monospace; -fx-font-size: 12px;"/>
</VBox>
<!-- Action Buttons -->
<HBox spacing="10" alignment="CENTER_RIGHT">
<Button fx:id="importAllButton" text="Import All" onAction="#onImportAll"
styleClass="primary-button" disable="true"/>
<HBox spacing="12" alignment="CENTER_RIGHT">
<Button text="Clear All" onAction="#onClearAll"/>
<Button fx:id="importAllButton" text="📥 Import All" onAction="#onImportAll"
styleClass="primary-button" disable="true"/>
</HBox>
</VBox>
</ScrollPane>

View File

@@ -9,10 +9,17 @@
fx:controller="org.example.se302.controller.MainController"
prefHeight="800.0" prefWidth="1200.0">
<!-- Top: Title Bar -->
<!-- Top: Title Bar with Theme Toggle -->
<top>
<VBox styleClass="header">
<Label text="Exam Scheduling System" styleClass="title-label"/>
<HBox alignment="CENTER_LEFT" spacing="20">
<padding>
<Insets top="10" right="20" bottom="10" left="20"/>
</padding>
<Label text="📅 Exam Scheduling System" styleClass="title-label" HBox.hgrow="ALWAYS"/>
<Button fx:id="themeToggleButton" text="🌙 Dark Mode" onAction="#onToggleTheme"
style="-fx-background-color: rgba(255,255,255,0.2); -fx-text-fill: white; -fx-border-color: rgba(255,255,255,0.3); -fx-border-width: 1; -fx-border-radius: 8; -fx-background-radius: 8; -fx-padding: 8 16; -fx-font-weight: 700;"/>
</HBox>
<Separator/>
</VBox>
</top>
@@ -21,27 +28,27 @@
<center>
<TabPane fx:id="mainTabPane" tabClosingPolicy="UNAVAILABLE">
<!-- Import Data Tab -->
<Tab fx:id="importTab" text="Import Data">
<Tab fx:id="importTab" text="📁 Import Data">
<fx:include source="import-view.fxml"/>
</Tab>
<!-- Students Tab -->
<Tab fx:id="studentsTab" text="Students">
<Tab fx:id="studentsTab" text="👤 Students">
<fx:include source="students-view.fxml"/>
</Tab>
<!-- Courses Tab -->
<Tab fx:id="coursesTab" text="Courses">
<Tab fx:id="coursesTab" text="📚 Courses">
<fx:include source="courses-view.fxml"/>
</Tab>
<!-- Classrooms Tab -->
<Tab fx:id="classroomsTab" text="Classrooms">
<Tab fx:id="classroomsTab" text="🏛️ Classrooms">
<fx:include source="classrooms-view.fxml"/>
</Tab>
<!-- Schedule Views Tab -->
<Tab fx:id="scheduleTab" text="Schedule Views">
<Tab fx:id="scheduleTab" text="📅 Schedule Views">
<fx:include source="schedule-views.fxml"/>
</Tab>
</TabPane>
@@ -51,9 +58,11 @@
<bottom>
<HBox styleClass="status-bar" spacing="10">
<padding>
<Insets top="5" right="10" bottom="5" left="10"/>
<Insets top="8" right="20" bottom="8" left="20"/>
</padding>
<Label fx:id="statusLabel" text="Ready - No data loaded"/>
<Label text="🟢" style="-fx-font-size: 10px;"/>
<Label fx:id="statusLabel" text="Ready - No data loaded" HBox.hgrow="ALWAYS"/>
<Label text="ExamFlow v2.0" style="-fx-font-size: 11px; -fx-text-fill: -fx-slate-400; -fx-font-weight: 700;"/>
</HBox>
</bottom>
</BorderPane>

View File

@@ -12,125 +12,131 @@
<BorderPane styleClass="content-pane">
<top>
<VBox spacing="15">
<VBox spacing="20">
<padding>
<Insets top="20" right="20" bottom="10" left="20"/>
<Insets top="40" right="40" bottom="20" left="40"/>
</padding>
<!-- Page Title -->
<Label text="📅 Calendar View - Exam Schedule Generator" styleClass="section-title"/>
<Label text="Configure and generate an optimized exam schedule using CSP algorithm."
wrapText="true" styleClass="description-label"/>
<VBox spacing="8">
<Label text="📅 Auto Schedule Generator" styleClass="section-title"/>
<Label text="Configure and generate an optimized exam schedule using CSP algorithm with intelligent heuristics."
wrapText="true" styleClass="description-label"/>
</VBox>
<Separator/>
<!-- Configuration Panel -->
<VBox spacing="15" styleClass="config-panel">
<Label text="Schedule Configuration" styleClass="subsection-title"/>
<VBox spacing="20" styleClass="config-panel">
<Label text="⚙️ Schedule Configuration" styleClass="subsection-title"/>
<!-- Row 1: Days and Slots -->
<HBox spacing="20" alignment="CENTER_LEFT">
<VBox spacing="5">
<Label text="Number of Days:"/>
<Spinner fx:id="numDaysSpinner" min="1" max="30" initialValue="5"
editable="true" prefWidth="100"/>
<!-- Row 1: Time Configuration -->
<GridPane hgap="16" vgap="12">
<columnConstraints>
<ColumnConstraints percentWidth="25"/>
<ColumnConstraints percentWidth="25"/>
<ColumnConstraints percentWidth="25"/>
<ColumnConstraints percentWidth="25"/>
</columnConstraints>
<VBox spacing="6" GridPane.columnIndex="0" GridPane.rowIndex="0">
<Label text="Number of Days" styleClass="stat-label"/>
<Spinner fx:id="numDaysSpinner" editable="true" prefWidth="120"/>
</VBox>
<VBox spacing="5">
<Label text="Slots per Day:"/>
<Spinner fx:id="slotsPerDaySpinner" min="1" max="10" initialValue="4"
editable="true" prefWidth="100"/>
<VBox spacing="6" GridPane.columnIndex="1" GridPane.rowIndex="0">
<Label text="Slots per Day" styleClass="stat-label"/>
<Spinner fx:id="slotsPerDaySpinner" editable="true" prefWidth="120"/>
</VBox>
<VBox spacing="5">
<Label text="Start Date:"/>
<DatePicker fx:id="startDatePicker" promptText="Select Start Date" prefWidth="150"/>
<VBox spacing="6" GridPane.columnIndex="2" GridPane.rowIndex="0">
<Label text="Start Date" styleClass="stat-label"/>
<DatePicker fx:id="startDatePicker" promptText="Select Date" prefWidth="150"/>
</VBox>
<VBox spacing="5">
<Label text="Slot Duration (min):"/>
<Spinner fx:id="slotDurationSpinner" min="30" max="240" initialValue="120"
editable="true" prefWidth="100"/>
</VBox>
</HBox>
<!-- Row 2: Strategy and Options -->
<HBox spacing="20" alignment="CENTER_LEFT">
<VBox spacing="5">
<Label text="Optimization Strategy:"/>
<ComboBox fx:id="strategyComboBox" prefWidth="200" promptText="Select Strategy"/>
<VBox spacing="6" GridPane.columnIndex="3" GridPane.rowIndex="0">
<Label text="Slot Duration (min)" styleClass="stat-label"/>
<Spinner fx:id="slotDurationSpinner" editable="true" prefWidth="120"/>
</VBox>
<VBox spacing="5">
<Label text="Day Start Time:"/>
<!-- Row 2: Strategy Configuration -->
<VBox spacing="6" GridPane.columnIndex="0" GridPane.rowIndex="1" GridPane.columnSpan="2">
<Label text="Optimization Strategy" styleClass="stat-label"/>
<ComboBox fx:id="strategyComboBox" prefWidth="250" promptText="Select Strategy"/>
</VBox>
<VBox spacing="6" GridPane.columnIndex="2" GridPane.rowIndex="1">
<Label text="Day Start Time" styleClass="stat-label"/>
<ComboBox fx:id="startTimeComboBox" prefWidth="120" promptText="09:00"/>
</VBox>
<VBox spacing="5" alignment="CENTER_LEFT">
<padding>
<Insets top="18"/>
</padding>
<CheckBox fx:id="allowBackToBackCheckBox" text="Allow back-to-back exams" selected="true"/>
<VBox spacing="6" alignment="CENTER_LEFT" GridPane.columnIndex="3" GridPane.rowIndex="1">
<Label text="Options" styleClass="stat-label"/>
<CheckBox fx:id="allowBackToBackCheckBox" text="Allow back-to-back" selected="true"/>
</VBox>
</HBox>
</GridPane>
<!-- Row 3: Summary -->
<HBox spacing="10" alignment="CENTER_LEFT" styleClass="summary-row">
<Label text="Configuration Summary:"/>
<Label fx:id="summaryLabel" text="5 days × 4 slots = 20 total time slots"
<!-- Summary -->
<HBox spacing="12" alignment="CENTER_LEFT" styleClass="summary-row">
<Label text="📊 Total Time Slots:" style="-fx-font-weight: 700;"/>
<Label fx:id="summaryLabel" text="5 days × 4 slots = 20 slots"
styleClass="summary-value"/>
</HBox>
</VBox>
<Separator/>
<!-- Action Buttons -->
<HBox spacing="15" alignment="CENTER_LEFT">
<!-- Action Bar -->
<HBox spacing="16" alignment="CENTER_LEFT">
<Button fx:id="generateButton" text="🚀 Generate Schedule"
onAction="#onGenerateSchedule" styleClass="primary-button" prefWidth="180"/>
onAction="#onGenerateSchedule" styleClass="primary-button"/>
<Button fx:id="cancelButton" text="Cancel" onAction="#onCancelGeneration"
disable="true" prefWidth="100"/>
disable="true"/>
<Region HBox.hgrow="ALWAYS"/>
<Label fx:id="statusLabel" text="Ready" styleClass="status-label"/>
</HBox>
<!-- Progress Container with Indicator -->
<VBox fx:id="progressContainer" spacing="8" visible="false" managed="false"
style="-fx-background-color: #f8f9fa; -fx-padding: 15; -fx-background-radius: 5;">
<HBox spacing="15" alignment="CENTER_LEFT">
<ProgressIndicator fx:id="progressIndicator" prefWidth="30" prefHeight="30"/>
<VBox spacing="3">
<!-- Progress Container -->
<VBox fx:id="progressContainer" spacing="12" visible="false" managed="false"
styleClass="card">
<HBox spacing="16" alignment="CENTER_LEFT">
<ProgressIndicator fx:id="progressIndicator" prefWidth="32" prefHeight="32"/>
<VBox spacing="4" HBox.hgrow="ALWAYS">
<Label fx:id="progressLabel" text="Initializing..."
style="-fx-font-weight: bold; -fx-font-size: 13;"/>
<ProgressBar fx:id="progressBar" prefWidth="350" progress="0"/>
style="-fx-font-weight: 700; -fx-font-size: 14px;"/>
<ProgressBar fx:id="progressBar" prefWidth="400" progress="0" maxWidth="Infinity"/>
</VBox>
</HBox>
<Label fx:id="progressDetailLabel" text="Please wait..."
style="-fx-text-fill: #7f8c8d; -fx-font-size: 11;"/>
style="-fx-text-fill: -fx-slate-600; -fx-font-size: 12px;"/>
</VBox>
</VBox>
</top>
<center>
<VBox spacing="15">
<VBox spacing="20">
<padding>
<Insets top="20" right="20" bottom="20" left="20"/>
<Insets top="20" right="40" bottom="40" left="40"/>
</padding>
<!-- Schedule Grid Container -->
<Label text="Generated Schedule" styleClass="subsection-title"/>
<!-- Schedule Grid Header -->
<HBox spacing="12" alignment="CENTER_LEFT">
<Label text="📆 Generated Schedule" styleClass="subsection-title"/>
<Region HBox.hgrow="ALWAYS"/>
<Button text="📥 Export PDF" styleClass="small-button"/>
</HBox>
<!-- Schedule Grid -->
<ScrollPane fx:id="scheduleScrollPane" fitToWidth="true" fitToHeight="false"
prefHeight="500" minHeight="300"
hbarPolicy="ALWAYS" vbarPolicy="ALWAYS"
VBox.vgrow="ALWAYS"
style="-fx-background-color: white; -fx-border-color: #bdc3c7; -fx-border-width: 1;">
style="-fx-background: -fx-surface; -fx-border-color: -fx-slate-200; -fx-border-width: 1; -fx-border-radius: 24; -fx-background-radius: 24;">
<GridPane fx:id="scheduleGrid" gridLinesVisible="true" styleClass="schedule-grid"
minWidth="800" minHeight="400">
<padding>
<Insets top="10" right="10" bottom="10" left="10"/>
</padding>
<!-- Grid will be populated dynamically -->
<Label text="Click 'Generate Schedule' to create an exam schedule"
GridPane.columnIndex="0" GridPane.rowIndex="0"
styleClass="placeholder-text" wrapText="true"/>
@@ -138,23 +144,23 @@
</ScrollPane>
<!-- Statistics Panel -->
<HBox spacing="30" alignment="CENTER_LEFT" styleClass="stats-panel">
<VBox spacing="3" alignment="CENTER">
<HBox spacing="24" alignment="CENTER_LEFT" styleClass="stats-panel">
<VBox spacing="4" alignment="CENTER">
<Label fx:id="totalCoursesLabel" text="0" styleClass="stat-value"/>
<Label text="Total Courses" styleClass="stat-label"/>
</VBox>
<Separator orientation="VERTICAL"/>
<VBox spacing="3" alignment="CENTER">
<VBox spacing="4" alignment="CENTER">
<Label fx:id="scheduledCoursesLabel" text="0" styleClass="stat-value"/>
<Label text="Scheduled" styleClass="stat-label"/>
</VBox>
<Separator orientation="VERTICAL"/>
<VBox spacing="3" alignment="CENTER">
<VBox spacing="4" alignment="CENTER">
<Label fx:id="classroomsUsedLabel" text="0" styleClass="stat-value"/>
<Label text="Classrooms Used" styleClass="stat-label"/>
</VBox>
<Separator orientation="VERTICAL"/>
<VBox spacing="3" alignment="CENTER">
<VBox spacing="4" alignment="CENTER">
<Label fx:id="generationTimeLabel" text="-" styleClass="stat-value"/>
<Label text="Generation Time" styleClass="stat-label"/>
</VBox>