267 lines
9.4 KiB
Java
267 lines
9.4 KiB
Java
package cz.jzitnik.controllers;
|
|
|
|
import cz.jzitnik.router.Route;
|
|
import cz.jzitnik.router.Router;
|
|
import cz.jzitnik.query.QueryOptions;
|
|
import cz.jzitnik.query.QueryResult;
|
|
import io.github.tomhula.jecnaapi.data.timetable.Lesson;
|
|
import io.github.tomhula.jecnaapi.data.timetable.LessonPeriod;
|
|
import io.github.tomhula.jecnaapi.data.timetable.LessonSpot;
|
|
import io.github.tomhula.jecnaapi.data.timetable.Timetable;
|
|
import io.github.tomhula.jecnaapi.data.timetable.TimetablePage;
|
|
import javafx.application.Platform;
|
|
import javafx.fxml.FXML;
|
|
import javafx.geometry.Insets;
|
|
import javafx.geometry.Pos;
|
|
import javafx.scene.control.*;
|
|
import javafx.scene.layout.*;
|
|
|
|
import kotlinx.datetime.DayOfWeek;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
|
|
@Route(path = "/timetable", fxml = "/timetable.fxml")
|
|
public class TimetableController extends DashboardBaseController {
|
|
|
|
@FXML
|
|
private GridPane timetableGrid;
|
|
|
|
@FXML
|
|
private ProgressIndicator loadingIndicator;
|
|
|
|
@FXML
|
|
private ScrollPane scrollPane;
|
|
|
|
private TimetablePage currentPage;
|
|
|
|
@Override
|
|
public void onNavigate(Map<String, Object> props) {
|
|
super.onNavigate(props);
|
|
loadTimetable();
|
|
}
|
|
|
|
private void loadTimetable() {
|
|
loadingIndicator.setVisible(true);
|
|
scrollPane.setVisible(false);
|
|
timetableGrid.getChildren().clear();
|
|
|
|
appState.getQueryClient().fetch("timetable:page", () -> {
|
|
try {
|
|
return appState.getClient().getTimetablePage().join();
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
return null;
|
|
}
|
|
}, QueryOptions.defaultOptions()).thenAccept(this::handleTimetableResult);
|
|
}
|
|
|
|
private void handleTimetableResult(QueryResult<TimetablePage> result) {
|
|
Platform.runLater(() -> {
|
|
loadingIndicator.setVisible(false);
|
|
|
|
if (result.isSuccess() && result.getData().isPresent()) {
|
|
scrollPane.setVisible(true);
|
|
currentPage = result.getData().get();
|
|
renderTimetable();
|
|
} else {
|
|
Label errorLabel = new Label("Failed to load timetable.");
|
|
errorLabel.getStyleClass().addAll("text-danger", "title-3");
|
|
timetableGrid.add(errorLabel, 0, 0);
|
|
timetableGrid.setAlignment(Pos.CENTER);
|
|
scrollPane.setVisible(true);
|
|
}
|
|
});
|
|
}
|
|
|
|
private void renderTimetable() {
|
|
timetableGrid.getChildren().clear();
|
|
timetableGrid.getColumnConstraints().clear();
|
|
timetableGrid.getRowConstraints().clear();
|
|
timetableGrid.setAlignment(Pos.CENTER);
|
|
|
|
Timetable timetable = currentPage.getTimetable();
|
|
List<LessonPeriod> periods = timetable.getLessonPeriods();
|
|
List<DayOfWeek> days = timetable.getDaysSorted();
|
|
|
|
ColumnConstraints dayCol = new ColumnConstraints();
|
|
dayCol.setMinWidth(120);
|
|
timetableGrid.getColumnConstraints().add(dayCol);
|
|
|
|
for (int i = 0; i < periods.size(); i++) {
|
|
LessonPeriod p = periods.get(i);
|
|
VBox header = new VBox(2);
|
|
header.setAlignment(Pos.CENTER);
|
|
header.getStyleClass().add("timetable-header");
|
|
|
|
Label indexLbl = new Label(String.valueOf(i));
|
|
indexLbl.getStyleClass().add("timetable-header-index");
|
|
|
|
Label timeLbl = new Label(p.toString());
|
|
timeLbl.getStyleClass().add("timetable-header-time");
|
|
|
|
header.getChildren().addAll(indexLbl, timeLbl);
|
|
|
|
ColumnConstraints col = new ColumnConstraints();
|
|
col.setMinWidth(110);
|
|
timetableGrid.getColumnConstraints().add(col);
|
|
|
|
timetableGrid.add(header, i + 1, 0);
|
|
}
|
|
|
|
int rowIndex = 1;
|
|
for (DayOfWeek day : days) {
|
|
VBox dayCell = new VBox();
|
|
dayCell.setAlignment(Pos.CENTER_RIGHT);
|
|
dayCell.getStyleClass().add("timetable-day-cell");
|
|
|
|
Label dayLabel = new Label(translateDay(day));
|
|
dayLabel.getStyleClass().addAll("timetable-day-label", "title-3");
|
|
dayCell.getChildren().add(dayLabel);
|
|
|
|
timetableGrid.add(dayCell, 0, rowIndex);
|
|
|
|
List<LessonSpot> spots = timetable.get(day);
|
|
if (spots != null) {
|
|
int colIndex = 1;
|
|
for (LessonSpot spot : spots) {
|
|
int span = spot.getPeriodSpan();
|
|
|
|
if (spot.isNotEmpty()) {
|
|
VBox cell = createLessonCell(spot);
|
|
timetableGrid.add(cell, colIndex, rowIndex, span, 1);
|
|
} else {
|
|
VBox emptyCell = new VBox();
|
|
emptyCell.getStyleClass().add("timetable-cell-empty");
|
|
timetableGrid.add(emptyCell, colIndex, rowIndex, span, 1);
|
|
}
|
|
|
|
colIndex += span;
|
|
}
|
|
}
|
|
|
|
rowIndex++;
|
|
}
|
|
}
|
|
|
|
private VBox createLessonCell(LessonSpot spot) {
|
|
VBox cell = new VBox(5);
|
|
cell.setAlignment(Pos.CENTER);
|
|
cell.getStyleClass().addAll("card", "timetable-cell");
|
|
|
|
if (spot.getSize() == 1) {
|
|
Lesson lesson = spot.getLesson(0);
|
|
addLessonInfoToCell(cell, lesson);
|
|
} else {
|
|
VBox groupContainer = new VBox(5);
|
|
groupContainer.setAlignment(Pos.CENTER);
|
|
|
|
for (int i = 0; i < spot.getSize(); i++) {
|
|
Lesson lesson = spot.getLesson(i);
|
|
VBox groupCell = new VBox(2);
|
|
groupCell.setAlignment(Pos.CENTER);
|
|
addLessonInfoToCell(groupCell, lesson);
|
|
|
|
if (lesson.getGroup() != null) {
|
|
Label groupLbl = new Label(lesson.getGroup());
|
|
groupLbl.getStyleClass().add("timetable-group-label");
|
|
groupCell.getChildren().add(0, groupLbl);
|
|
}
|
|
|
|
groupContainer.getChildren().add(groupCell);
|
|
|
|
if (i < spot.getSize() - 1) {
|
|
Separator sep = new Separator(javafx.geometry.Orientation.HORIZONTAL);
|
|
groupContainer.getChildren().add(sep);
|
|
}
|
|
}
|
|
cell.getChildren().add(groupContainer);
|
|
}
|
|
|
|
cell.setOnMouseClicked(e -> showLessonDetails(spot));
|
|
|
|
return cell;
|
|
}
|
|
|
|
private void addLessonInfoToCell(VBox cell, Lesson lesson) {
|
|
Label subjectLbl = new Label(lesson.getSubjectName().getShort() != null ? lesson.getSubjectName().getShort() : lesson.getSubjectName().getFull());
|
|
subjectLbl.getStyleClass().add("timetable-subject");
|
|
|
|
HBox bottomInfo = new HBox(5);
|
|
bottomInfo.setAlignment(Pos.CENTER);
|
|
|
|
if (lesson.getTeacherName() != null) {
|
|
Label teacherLbl = new Label(lesson.getTeacherName().getShort() != null ? lesson.getTeacherName().getShort() : lesson.getTeacherName().getFull());
|
|
teacherLbl.getStyleClass().add("timetable-teacher");
|
|
bottomInfo.getChildren().add(teacherLbl);
|
|
}
|
|
|
|
if (lesson.getClassroom() != null) {
|
|
Label roomLbl = new Label(lesson.getClassroom());
|
|
roomLbl.getStyleClass().add("timetable-room");
|
|
bottomInfo.getChildren().add(roomLbl);
|
|
}
|
|
|
|
cell.getChildren().addAll(subjectLbl, bottomInfo);
|
|
}
|
|
|
|
private void showLessonDetails(LessonSpot spot) {
|
|
Dialog<Void> dialog = new Dialog<>();
|
|
dialog.setTitle("Detail hodiny");
|
|
dialog.setHeaderText(null);
|
|
dialog.getDialogPane().getButtonTypes().add(ButtonType.CLOSE);
|
|
|
|
VBox content = new VBox(15);
|
|
content.setPadding(new Insets(20));
|
|
|
|
for (Lesson lesson : spot) {
|
|
VBox lessonInfo = new VBox(5);
|
|
lessonInfo.getStyleClass().add("timetable-detail-box");
|
|
|
|
Label title = new Label(lesson.getSubjectName().getFull());
|
|
title.getStyleClass().add("title-3");
|
|
lessonInfo.getChildren().add(title);
|
|
|
|
GridPane grid = new GridPane();
|
|
grid.setHgap(10);
|
|
grid.setVgap(5);
|
|
|
|
int row = 0;
|
|
if (lesson.getTeacherName() != null) {
|
|
grid.add(new Label("Učitel:"), 0, row);
|
|
grid.add(new Label(lesson.getTeacherName().getFull()), 1, row++);
|
|
}
|
|
if (lesson.getClassroom() != null) {
|
|
grid.add(new Label("Učebna:"), 0, row);
|
|
grid.add(new Label(lesson.getClassroom()), 1, row++);
|
|
}
|
|
if (lesson.getGroup() != null) {
|
|
grid.add(new Label("Skupina:"), 0, row);
|
|
grid.add(new Label(lesson.getGroup()), 1, row++);
|
|
}
|
|
|
|
lessonInfo.getChildren().add(grid);
|
|
content.getChildren().add(lessonInfo);
|
|
}
|
|
|
|
dialog.getDialogPane().setContent(content);
|
|
dialog.show();
|
|
}
|
|
|
|
private String translateDay(DayOfWeek day) {
|
|
return switch (day) {
|
|
case MONDAY -> "Pondělí";
|
|
case TUESDAY -> "Úterý";
|
|
case WEDNESDAY -> "Středa";
|
|
case THURSDAY -> "Čtvrtek";
|
|
case FRIDAY -> "Pátek";
|
|
case SATURDAY -> "Sobota";
|
|
case SUNDAY -> "Neděle";
|
|
};
|
|
}
|
|
|
|
@FXML
|
|
protected void onBackToDashboard() {
|
|
Router.getInstance().navigate("/dashboard");
|
|
}
|
|
}
|