diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/artifacts/Bookings_jar.xml b/.idea/artifacts/Bookings_jar.xml new file mode 100644 index 0000000..d46bedf --- /dev/null +++ b/.idea/artifacts/Bookings_jar.xml @@ -0,0 +1,23 @@ + + + $PROJECT_DIR$/out/artifacts/Bookings_jar + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml deleted file mode 100644 index 1bec35e..0000000 --- a/.idea/codeStyles/Project.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml deleted file mode 100644 index 79ee123..0000000 --- a/.idea/codeStyles/codeStyleConfig.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/dataSources.local.xml b/.idea/dataSources.local.xml new file mode 100644 index 0000000..7a15961 --- /dev/null +++ b/.idea/dataSources.local.xml @@ -0,0 +1,17 @@ + + + + + + " + + + no-auth + + + + + + + + \ No newline at end of file diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..be8638c --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,17 @@ + + + + + sqlite.xerial + true + org.sqlite.JDBC + jdbc:sqlite:C:\Users\mario\IdeaProjects\Bookings\assets\database\bookings.db + $ProjectFileDir$ + + + file://$APPLICATION_CONFIG_DIR$/jdbc-drivers/Xerial SQLiteJDBC/3.39.2/sqlite-jdbc-3.39.2.jar + + + + + \ No newline at end of file diff --git a/.idea/dataSources/0ae1950a-c940-4c90-bdb8-2907a895397f.xml b/.idea/dataSources/0ae1950a-c940-4c90-bdb8-2907a895397f.xml new file mode 100644 index 0000000..008fe62 --- /dev/null +++ b/.idea/dataSources/0ae1950a-c940-4c90-bdb8-2907a895397f.xml @@ -0,0 +1,1488 @@ + + + + + 3.39.2 + + + + + + + + + + + + + + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + 1 + 1 + + + window + + + 1 + 1 + + + 1 + 1 + + + window + + + 1 + 1 + + + + + 1 + + + 1 + + + 1 + + + + 1 + + + 1 + + + window + + + 1 + + + window + + + 1 + + + + 1 + + + 1 + + + 1 + + + 1 + + + + + 1 + + + window + + + 1 + + + 1 + + + window + + + window + + + 1 + + + 1 + + + 1 + + + window + + + + 1 + + + window + + + 1 + + + 1 + + + 1 + + + 1 + + + 1 + + + + 1 + window + + + window + + + 1 + + + 1 + window + + + 1 + + + 1 + + + + 1 + + + window + + + window + + + + 1 + + + 1 + + + window + + + + + + 1 + + + 1 + + + 1 + + + 1 + + + + window + + + 1 + + + 1 + + + window + + + 1 + + + + + window + + + 1 + + + window + + + window + + + window + + + 1 + + + 1 + + + window + + + 1 + + + 1 + + + aggregate + + + aggregate + + + + + + + + + + + + + + + + aggregate + + + + aggregate + + + + + + + + + aggregate + + + + + + + + + + + + + aggregate + + + + + + + + + + + + + + + + + + + + 1 + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + R + + + 1 + + + 2 + + + 3 + + + R + + + R + + + R + + + 1 + + + 2 + + + 3 + + + R + + + R + + + 1 + + + 2 + + + 3 + + + R + + + 1 + + + 2 + + + R + + + R + + + R + + + R + + + 1 + + + 2 + + + R + + + R + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + 3 + + + R + + + 1 + + + 2 + + + 3 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + 3 + + + R + + + 1 + + + R + + + 1 + + + R + + + R + + + R + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + R + + + R + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + 3 + + + R + + + R + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + R + + + 1 + + + 2 + + + R + + + R + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + 3 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + 2 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + + R + + + 1 + + +
+
+
+
+ 1 +
+ + 1 +
+ + + 1 + INTEGER|0s + 1 + + + INTEGER|0s + 1 + 2 + + + TEXT|0s + 1 + 3 + + + TEXT|0s + 1 + 4 + + + TEXT|0s + 1 + 5 + + + TEXT|0s + 1 + 6 + + + TEXT|0s + 1 + 7 + + + INTEGER|0s + 1 + 8 + + + id + 1 + + + TEXT|0s + 1 + + + TEXT|0s + 1 + 2 + + + TEXT|0s + 1 + 3 + + + name + 1 + 1 + + + name + 1 + sqlite_autoindex_guests_1 + + + 1 + INTEGER|0s + 1 + + + TEXT|0s + 1 + 2 + + + id + 1 + + + TEXT|0s + 1 + + + TEXT|0s + 2 + + + name + 1 + 1 + + + name + 1 + sqlite_autoindex_settings_1 + + + TEXT|0s + 1 + + + TEXT|0s + 2 + + + TEXT|0s + 3 + + + INT|0s + 4 + + + TEXT|0s + 5 + + + 1 + + + 2 + + + TEXT|0s + 1 + + + TEXT|0s + 1 + 2 + + + INTEGER|0s + 1 + 3 + + + INTEGER|0s + 1 + 4 + + + INTEGER|0s + 1 + 5 + + + username + 1 + 1 + + + username + 1 + sqlite_autoindex_users_1 + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 9462bc8..aa00ffa 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,9 +1,7 @@ - - - + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml deleted file mode 100644 index 4251b72..0000000 --- a/.idea/kotlinc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml index 0ff3673..0abcc97 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,14 +1,12 @@ + - - - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..74c0acf --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1673473439642 + + + + + + + + + + + + \ No newline at end of file diff --git a/assets/database/bookings.db b/assets/database/bookings.db new file mode 100644 index 0000000..d992bf9 Binary files /dev/null and b/assets/database/bookings.db differ diff --git a/pom.xml b/pom.xml index c4ae276..cdf759a 100644 --- a/pom.xml +++ b/pom.xml @@ -11,11 +11,31 @@ UTF-8 - 5.9.0 - 1.7.22 + 5.9.2 + + org.apache.pdfbox + pdfbox + 2.0.27 + + + org.controlsfx + controlsfx + 11.1.2 + + + org.xerial + sqlite-jdbc + 3.40.0.0 + + + org.openjfx + javafx-media + 19 + + org.openjfx javafx-controls @@ -39,15 +59,9 @@ ${junit.version} test - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - ${kotlin.version} - - ${project.basedir}/src/main/kotlin org.apache.maven.plugins @@ -79,30 +93,6 @@ - - org.jetbrains.kotlin - kotlin-maven-plugin - ${kotlin.version} - - - compile - process-sources - - compile - - - - test-compile - test-compile - - test-compile - - - - - 11 - - \ No newline at end of file diff --git a/src/main/java/com/github/mariosplen/bookings/Bookings.java b/src/main/java/com/github/mariosplen/bookings/Bookings.java new file mode 100644 index 0000000..f2f2cd7 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/Bookings.java @@ -0,0 +1,20 @@ +package com.github.mariosplen.bookings; + +import com.github.mariosplen.bookings.util.Nav; +import javafx.application.Application; +import javafx.stage.Stage; + +import java.io.IOException; + +public class Bookings extends Application { + + public static void main(String[] args) { + launch(); + } + + @Override + public void start(Stage stage) throws IOException { + Nav.toLoading(stage); + } +} + diff --git a/src/main/java/com/github/mariosplen/bookings/Main.java b/src/main/java/com/github/mariosplen/bookings/Main.java new file mode 100644 index 0000000..1a0375b --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/Main.java @@ -0,0 +1,8 @@ +package com.github.mariosplen.bookings; + + +public class Main { + public static void main(String[] args) { + Bookings.main(args); + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/MainView.java b/src/main/java/com/github/mariosplen/bookings/controllers/MainView.java new file mode 100644 index 0000000..5845bb1 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/MainView.java @@ -0,0 +1,67 @@ +package com.github.mariosplen.bookings.controllers; + + +import com.github.mariosplen.bookings.models.User; +import com.github.mariosplen.bookings.util.Nav; +import javafx.application.Platform; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.Node; +import javafx.scene.control.Button; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.text.Text; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + +public class MainView implements Initializable { + private final User user; + public HBox mainViewUsernameHBox; + public Text mainViewUsername; + public BorderPane contentPane; + + + @FXML + private Button backBtn; + + + public MainView(User user, Node content) { + this.user = user; + Platform.runLater(() -> contentPane.setCenter(content)); + + + } + + public Button getBackBtn() { + return backBtn; + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + + if (user != null) { + mainViewUsername.setText(user.username().toUpperCase()); + backBtn.setOnAction(event -> { + try { + Nav.toHome(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } else { + mainViewUsernameHBox.setVisible(false); + backBtn.setOnAction(event -> { + try { + Nav.user = null; + Nav.toLogin(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } + } + + +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/books/BooksView.java b/src/main/java/com/github/mariosplen/bookings/controllers/books/BooksView.java new file mode 100644 index 0000000..e33e70d --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/books/BooksView.java @@ -0,0 +1,141 @@ +package com.github.mariosplen.bookings.controllers.books; + + +import com.github.mariosplen.bookings.models.Book; +import com.github.mariosplen.bookings.models.BookDAO; +import com.github.mariosplen.bookings.models.Guest; +import com.github.mariosplen.bookings.models.GuestDAO; +import com.github.mariosplen.bookings.util.ReceiptGenerator; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleObjectProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; + +import java.io.IOException; +import java.net.URL; +import java.sql.SQLException; +import java.util.Objects; +import java.util.ResourceBundle; + +public class BooksView implements Initializable { + + + @FXML + ObservableList books; + @FXML + private TableView bookTableView; + @FXML + private TableColumn + saveButtonColumn, + deleteButtonColumn; + @FXML + private TableColumn + room_id, + nights, + price; + @FXML + private TableColumn + check_in, + check_out, + guest_name, + room_category, + date; + + + private void tableViewValues() throws SQLException, ClassNotFoundException { + ObservableList roomObservableList = BookDAO.getBooks(); + saveButtonColumn.setCellValueFactory(param -> new SimpleObjectProperty<>(new Button("Save"))); + saveButtonColumn.setCellFactory(param -> new TableCell<>() { + final Button button = new Button("Save"); + + @Override + protected void updateItem(Button item, boolean empty) { + button.getStyleClass().add("verySmallBtn"); + super.updateItem(item, empty); + if (empty) { + setGraphic(null); + } else { + button.setOnAction(event -> { + Book book = getTableView().getItems().get(getIndex()); + try { + ReceiptGenerator receiptGenerator = new ReceiptGenerator(); + receiptGenerator.genReceipt(GuestDAO.getGuests().stream() + .map(Guest::name) + .filter(name -> Objects.equals(name, book.guestName())) + .findFirst() + .orElse(null), + book.checkIn(), + book.checkOut(), + book.totalPrice() + ); + } catch (IOException | SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }); + setGraphic(button); + } + } + }); + deleteButtonColumn.setCellFactory(param -> new TableCell<>() { + final Button button = new Button("Delete"); + + + @Override + protected void updateItem(Button item, boolean empty) { + button.getStyleClass().add("verySmallRedBtn"); + super.updateItem(item, empty); + if (empty) { + setGraphic(null); + } else { + button.setOnAction(event -> { + Book book = getTableView().getItems().get(getIndex()); + try { + + // Delete the book from the database using the BookDAO class + BookDAO.deleteBook(book.id()); + // Remove the book from the table's data + books.remove(book); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + try { + tableViewValues(); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }); + setGraphic(button); + } + } + }); + + guest_name.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().guestName())); + room_id.setCellValueFactory(p -> new SimpleIntegerProperty(p.getValue().roomId())); + check_in.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().checkIn().toString())); + check_out.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().checkOut().toString())); + date.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().date().toString())); + room_category.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().roomCategory())); + price.setCellValueFactory(p -> new SimpleIntegerProperty(p.getValue().totalPrice())); + nights.setCellValueFactory(p -> new SimpleIntegerProperty(p.getValue().checkIn().until(p.getValue().checkOut()).getDays())); + + bookTableView.setItems(roomObservableList); + } + + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + + try { + books = BookDAO.getBooks(); + tableViewValues(); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/calendar/CalendarView.java b/src/main/java/com/github/mariosplen/bookings/controllers/calendar/CalendarView.java new file mode 100644 index 0000000..f211a4a --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/calendar/CalendarView.java @@ -0,0 +1,160 @@ +package com.github.mariosplen.bookings.controllers.calendar; + + +import com.github.mariosplen.bookings.models.BookDAO; +import com.github.mariosplen.bookings.models.Room; +import com.github.mariosplen.bookings.models.RoomDAO; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.geometry.Insets; +import javafx.scene.control.DatePicker; +import javafx.scene.control.Label; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.GridPane; + +import java.net.URL; +import java.sql.SQLException; +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; + +public class CalendarView implements Initializable { + Map> roomBookDates; + @FXML + private GridPane gridPane; + @FXML + private DatePicker fromDP; + @FXML + private DatePicker toDP; + private LocalDate fromDate; + private List rooms; + + // Initializes the calendar view when it is loaded + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + // Get rooms from database + try { + rooms = RoomDAO.getRooms(); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + + // Set default dates for the from and to date pickers + fromDP.setValue(YearMonth.now().atDay(1)); + toDP.setValue(YearMonth.now().atEndOfMonth()); + + + setCalendarData(); + + } + + @FXML + private void setCalendarData() { + + gridPane.getChildren().clear(); + + // Get values from the datePickers + fromDate = fromDP.getValue(); + LocalDate toDate = toDP.getValue(); + + // Get a list of all the dates between the start and end dates + List allDates = new ArrayList<>(fromDate.datesUntil(toDate).toList()); + + // Set the calendar tag + Label roomTag = new Label("Room"); + roomTag.getStyleClass().add("calendarCellTagWhite"); + roomTag.setPadding(new Insets(2)); + gridPane.add(roomTag, 0, 0); + + // Set the rooms in the calendar grid + for (int i = 0; i < rooms.size(); i++) { + Label roomIdText = new Label(String.valueOf(rooms.get(i).id())); + roomIdText.getStyleClass().add("calendarCellTagBlack"); + BorderPane centered = new BorderPane(); + centered.setCenter(roomIdText); + gridPane.addRow(i + 1, centered); + } + + + // Set the dates in the calendar grid + for (int i = 0; i < allDates.size(); i++) { + Label dateText = new Label(allDates.get(i).toString()); + dateText.getStyleClass().add("calendarCellTagWhite"); + dateText.setPadding(new Insets(2, 8, 2, 8)); + BorderPane centered = new BorderPane(); + centered.setCenter(dateText); + gridPane.addColumn(i + 1, centered); + } + + + // Get a map of room bookings, with the room id as the key and a list of booked dates as the value + try { + roomBookDates = BookDAO.getRoomBookDates(); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + + // Fill gridPane with available ColoredItems + for (int r = 0; r < rooms.size(); r++) { + for (int c = 0; c < allDates.size(); c++) { + ColoredItem box = new ColoredItem(); + BorderPane centered = new BorderPane(); + centered.setCenter(box); + gridPane.add(centered, c + 1, r + 1); + } + } + + + roomBookDates.forEach((integer, localDates) -> { + for (int i = 0; i < rooms.size(); i++) { + if (String.valueOf(rooms.get(i).id()).equals(String.valueOf(integer))) { + for (LocalDate date : localDates) { + for (int j = 0; j < allDates.size(); j++) { + if (allDates.get(j).equals(date)) { + int finalI = i; + int finalJ = j; + gridPane.getChildren().forEach(node -> { + if (GridPane.getColumnIndex(node) == (finalJ + 1) && GridPane.getRowIndex(node) == (finalI + 1)) { + node.setDisable(true); + Tooltip.install(node, new Tooltip("Book_id = " + integer)); + } + }); + } + } + + } + } + } + + }); + } + + public void onNextMonthClk() { + LocalDate initial = fromDate.plusMonths(1); + + LocalDate nextStartOfMonth = initial.withDayOfMonth(1); + LocalDate nextEndOfMonth = + initial.withDayOfMonth(initial.getMonth().length(initial.isLeapYear())); + + fromDP.setValue(nextStartOfMonth); + toDP.setValue(nextEndOfMonth); + setCalendarData(); + } + + public void onPrevMonthClk() { + + LocalDate initial = fromDate.minusMonths(1); + + LocalDate prevStartOfMonth = initial.withDayOfMonth(1); + LocalDate prevEndOfMonth = + initial.withDayOfMonth(initial.getMonth().length(initial.isLeapYear())); + + fromDP.setValue(prevStartOfMonth); + toDP.setValue(prevEndOfMonth); + setCalendarData(); + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/calendar/ColoredItem.java b/src/main/java/com/github/mariosplen/bookings/controllers/calendar/ColoredItem.java new file mode 100644 index 0000000..a3a3828 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/calendar/ColoredItem.java @@ -0,0 +1,15 @@ +package com.github.mariosplen.bookings.controllers.calendar; + +import javafx.scene.shape.Rectangle; + +public class ColoredItem extends Rectangle { + + + public ColoredItem() { + setWidth(127); + setHeight(30); + getStyleClass().add("calendarCell"); + + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/guests/GuestsView.java b/src/main/java/com/github/mariosplen/bookings/controllers/guests/GuestsView.java new file mode 100644 index 0000000..2c50df5 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/guests/GuestsView.java @@ -0,0 +1,99 @@ +package com.github.mariosplen.bookings.controllers.guests; + + +import com.github.mariosplen.bookings.models.Guest; +import com.github.mariosplen.bookings.models.GuestDAO; +import javafx.collections.FXCollections; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.TextField; +import org.controlsfx.control.SearchableComboBox; + +import java.net.URL; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.function.Function; +import java.util.stream.Collectors; + +public class GuestsView implements Initializable { + @FXML + private Label msg; + @FXML + private Button selectedBtn; + @FXML + private TextField selectedTF; + private Guest guest; + @FXML + private SearchableComboBox usersSearchBox; + private String selectedInfoToEdit; + private Map guestMap; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + // Load the list of guests from the database + try { + List guestList = GuestDAO.getGuests(); + guestMap = guestList.stream().collect(Collectors.toMap(Guest::name, Function.identity())); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + + // Populate the searchable combo box with the names of the guests + usersSearchBox.setItems(FXCollections.observableArrayList(guestMap.keySet())); + } + + public void clickedEditSelector(ActionEvent actionEvent) { + msg.setVisible(false); + // Get the text of the button that was clicked + selectedInfoToEdit = ((Button) actionEvent.getSource()).getText(); + // Set the text of the selected button to the selected info to edit + selectedBtn.setText(selectedInfoToEdit); + // Find the selected guest based on the selected name in the combo box + guest = guestMap.get(usersSearchBox.getValue()); + + if (selectedInfoToEdit != null) { + // Enable editing for the selected text field + selectedTF.setEditable(true); + } + + if (guest != null) { + // Set the text of the selected text field to the selected info for the guest + assert selectedInfoToEdit != null; + selectedTF.setText(selectedInfoToEdit); + } + } + + public void selectedNewUserClicked() { + msg.setVisible(false); + // Find the selected guest based on the selected name in the combo box + guest = guestMap.get(usersSearchBox.getValue()); + + if (guest != null && selectedInfoToEdit != null) { + // Set the text of the selected text field to the selected info for the guest + selectedTF.setText(selectedInfoToEdit); + } + } + + + public void onSaveClicked() throws SQLException, ClassNotFoundException { + String databasePar = selectedInfoToEdit; + msg.setVisible(false); + if (databasePar != null) { + + GuestDAO.updateData(guest.name(), databasePar, selectedTF.getText()); + + // Refresh the list of guests from the database + guestMap = GuestDAO.getGuests().stream().collect(Collectors.toMap(Guest::name, Function.identity())); + + // Update the items in the combo box to reflect the updated list of guests + usersSearchBox.setItems(FXCollections.observableArrayList(guestMap.keySet())); + msg.setVisible(true); + } + + } +} \ No newline at end of file diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/home/HomeView.java b/src/main/java/com/github/mariosplen/bookings/controllers/home/HomeView.java new file mode 100644 index 0000000..e370140 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/home/HomeView.java @@ -0,0 +1,96 @@ +package com.github.mariosplen.bookings.controllers.home; + + +import com.github.mariosplen.bookings.util.Nav; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.Button; +import javafx.scene.layout.HBox; + +import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; + + +public class HomeView implements Initializable { + + + @FXML + private Button newGuestBtn, calendarBtn, guestsButton, usersButton, checkInBtn, booksBtn; + @FXML + private HBox logoutButton; + + + public void refresh() { + if (Nav.user.canManageGuests()) { + guestsButton.setDisable(false); + } + if (Nav.user.canManageUsers()) { + usersButton.setDisable(false); + } + if (Nav.user.canDoBasic()) { + checkInBtn.setDisable(false); + newGuestBtn.setDisable(false); + calendarBtn.setDisable(false); + booksBtn.setDisable(false); + } + } + + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + refresh(); + + newGuestBtn.setOnAction(actionEvent -> { + try { + Nav.toNewGuest(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + calendarBtn.setOnAction(actionEvent -> { + try { + Nav.toCalendar(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + guestsButton.setOnAction(actionEvent -> { + try { + Nav.toGuests(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + usersButton.setOnAction(actionEvent -> { + try { + Nav.toUsers(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + logoutButton.setOnMouseClicked(mouseEvent -> { + try { + Nav.toLogin(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + checkInBtn.setOnAction(actionEvent -> { + try { + Nav.toReservation(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + booksBtn.setOnAction(actionEvent -> { + try { + + Nav.toBooks(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/loading/LoadingView.java b/src/main/java/com/github/mariosplen/bookings/controllers/loading/LoadingView.java new file mode 100644 index 0000000..a447add --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/loading/LoadingView.java @@ -0,0 +1,96 @@ +package com.github.mariosplen.bookings.controllers.loading; + +import com.github.mariosplen.bookings.util.Nav; +import javafx.animation.PauseTransition; +import javafx.animation.ScaleTransition; +import javafx.animation.SequentialTransition; +import javafx.animation.TranslateTransition; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.media.Media; +import javafx.scene.media.MediaPlayer; +import javafx.scene.media.MediaView; +import javafx.scene.text.Text; +import javafx.util.Duration; + +import java.io.IOException; +import java.net.URL; +import java.util.Objects; +import java.util.ResourceBundle; + +public class LoadingView implements Initializable { + @FXML + private Text shadow1, shadow2, title; + @FXML + private MediaView intro; + + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + + // Start the animations + playAnimations(); + + // Animations end at approximately 7.5 seconds, then continue + PauseTransition delay = new PauseTransition(Duration.seconds(7.5)); + delay.setOnFinished((ActionEvent) -> { + try { + goToSignIn(); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + delay.play(); + } + + private void goToSignIn() throws IOException { + + Nav.toLogin(); + + } + + private void playAnimations() { + // Instant Scale down + ScaleTransition scaleDown = new ScaleTransition(Duration.millis(0.1), title); + scaleDown.setToX(0); + scaleDown.setToY(0); + + // Scale up + ScaleTransition scaleUp = new ScaleTransition(Duration.seconds(2), title); + scaleUp.setByX(1f); + scaleUp.setByY(1f); + + // Slide up + TranslateTransition slideUp = new TranslateTransition(Duration.seconds(1), title); + slideUp.setByY(-211); + + // Fade in the shadows + TranslateTransition firstShadow = new TranslateTransition(Duration.seconds(0.1), shadow1); + firstShadow.setByY(+25); + TranslateTransition secondShadow = new TranslateTransition(Duration.seconds(0.1), shadow2); + secondShadow.setByY(+50); + + // Play the transitions in sequence + SequentialTransition sequentialTransition = new SequentialTransition(); + sequentialTransition.getChildren().addAll(scaleDown, scaleUp, slideUp); + sequentialTransition.setOnFinished(actionEvent -> { + shadow1.setVisible(true); + shadow2.setVisible(true); + firstShadow.play(); + secondShadow.play(); + }); + // Set up the intro video + MediaPlayer player = new MediaPlayer(new Media(Objects.requireNonNull(getClass().getResource("/com/github/mariosplen/bookings/media/intro/intro.mp4")).toExternalForm())); + + player.setAutoPlay(true); + + + intro.setMediaPlayer(player); + + // Show the title when the video ends + player.setOnEndOfMedia(() -> { + title.setVisible(true); + sequentialTransition.play(); + }); + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/login/LoginView.java b/src/main/java/com/github/mariosplen/bookings/controllers/login/LoginView.java new file mode 100644 index 0000000..65b7b51 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/login/LoginView.java @@ -0,0 +1,52 @@ +package com.github.mariosplen.bookings.controllers.login; + +import com.github.mariosplen.bookings.models.User; +import com.github.mariosplen.bookings.models.UserDAO; +import com.github.mariosplen.bookings.util.Nav; +import javafx.fxml.FXML; +import javafx.scene.control.PasswordField; +import javafx.scene.control.TextField; +import javafx.scene.text.Text; + +import java.io.IOException; +import java.sql.SQLException; + +public class LoginView { + @FXML + private PasswordField passwordTF; + @FXML + private TextField usernameTF; + @FXML + private Text errorMsg; + + + @FXML + private void onLoginBtnClicked() throws SQLException, ClassNotFoundException, IOException { + + // Try to log the user in + User user = UserDAO.login(usernameTF.getText(), passwordTF.getText()); + + // If the login fails, display an error message + if (user == null) { + errorMsg.setVisible(true); + return; + } + Nav.user = user; + Nav.toHome(); + + + } + + @FXML + private void onForgotPassHLClicked() throws IOException { + Nav.toRecovery(); + } + + + @FXML + private void onRegisterHLClicked() throws IOException { + Nav.toRegister(); + } + + +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/new_guest/NewGuestView.java b/src/main/java/com/github/mariosplen/bookings/controllers/new_guest/NewGuestView.java new file mode 100644 index 0000000..922f8fa --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/new_guest/NewGuestView.java @@ -0,0 +1,30 @@ +package com.github.mariosplen.bookings.controllers.new_guest; + +import com.github.mariosplen.bookings.models.GuestDAO; +import javafx.fxml.FXML; +import javafx.scene.control.TextField; +import javafx.scene.text.Text; + +import java.sql.SQLException; + +public class NewGuestView { + @FXML + private TextField nameTF, phoneTF, emailTF; + @FXML + private Text errorMsg; + + public void onSaveClicked() throws SQLException, ClassNotFoundException { + errorMsg.setText(""); + if (nameTF.getText().isBlank() || phoneTF.getText().isBlank() || emailTF.getText().isBlank()) { + errorMsg.setText("Wrong Parameters"); + return; + } + + + GuestDAO.addGuest(nameTF.getText(), phoneTF.getText(), emailTF.getText()); + errorMsg.setText("New Guest Added!"); + nameTF.setText(""); + phoneTF.setText(""); + emailTF.setText(""); + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/recovery/RecoverView.java b/src/main/java/com/github/mariosplen/bookings/controllers/recovery/RecoverView.java new file mode 100644 index 0000000..4c31ec1 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/recovery/RecoverView.java @@ -0,0 +1,51 @@ +package com.github.mariosplen.bookings.controllers.recovery; + +import com.github.mariosplen.bookings.models.SettingsDAO; +import com.github.mariosplen.bookings.models.User; +import com.github.mariosplen.bookings.models.UserDAO; +import com.github.mariosplen.bookings.util.Nav; +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.PasswordField; +import javafx.scene.control.TextField; +import javafx.scene.text.Text; + +import java.io.IOException; +import java.sql.SQLException; + +public class RecoverView { + + @FXML + private Text showPasswordTxt; + @FXML + private Label errorMsg; + @FXML + private PasswordField hotelKey; + @FXML + private TextField usernameTF; + + + public void onBackButtonClicked() throws IOException { + Nav.toLogin(); + } + + public void onShowBtnClicked() throws SQLException, ClassNotFoundException { + errorMsg.setVisible(false); + showPasswordTxt.setVisible(false); + + // Check if hotel key is correct + if (hotelKey.getText().equals(SettingsDAO.getHotelKey())) { + // Check if user exists + for (User user : UserDAO.getUsers()) { + if (user.username().equals(usernameTF.getText())) { + errorMsg.setVisible(false); + showPasswordTxt.setText(showPasswordTxt.getText() + user.password()); + showPasswordTxt.setVisible(true); + return; + } + } + } + // If hotel key is incorrect or user does not exist, show error message + errorMsg.setVisible(true); + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/register/RegisterView.java b/src/main/java/com/github/mariosplen/bookings/controllers/register/RegisterView.java new file mode 100644 index 0000000..f5506ef --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/register/RegisterView.java @@ -0,0 +1,65 @@ +package com.github.mariosplen.bookings.controllers.register; + +import com.github.mariosplen.bookings.models.SettingsDAO; +import com.github.mariosplen.bookings.models.User; +import com.github.mariosplen.bookings.models.UserDAO; +import com.github.mariosplen.bookings.util.Nav; +import javafx.fxml.FXML; +import javafx.scene.control.CheckBox; +import javafx.scene.control.PasswordField; +import javafx.scene.control.TextField; +import javafx.scene.text.Text; + +import java.io.IOException; +import java.sql.SQLException; + +public class RegisterView { + @FXML + private Text errorMsg; + @FXML + private PasswordField hotelKeyTF, passwordTF; + @FXML + private TextField usernameTF; + @FXML + private CheckBox editUsersCB; + @FXML + private CheckBox editGuestsCB; + @FXML + private CheckBox basicCB; + + + @FXML + private void onRegisterBtnClicked() throws IOException, SQLException, ClassNotFoundException { + + errorMsg.setVisible(false); + + // Check if username, password, and hotel key are not blank + // Check if hotel key is correct + if (usernameTF.getText().isBlank() || passwordTF.getText().isBlank() || !hotelKeyTF.getText().equals(SettingsDAO.getHotelKey())) { + errorMsg.setText("Please enter a username, password, and hotel key (ask the owner for the hotel key)"); + errorMsg.setVisible(true); + return; + } + + // Check if username is already taken + for (User user : UserDAO.getUsers()) { + if (user.username().equals(usernameTF.getText())) { + errorMsg.setText("A user with this username already exists"); + errorMsg.setVisible(true); + return; + } + } + + // If no errors, add new user to the database + if (!errorMsg.isVisible()) { + UserDAO.addUser( + usernameTF.getText(), + passwordTF.getText(), + basicCB.isSelected(), + editGuestsCB.isSelected(), + editUsersCB.isSelected() + ); + Nav.toLogin(); + } + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/reservation/ReservationDetailsView.java b/src/main/java/com/github/mariosplen/bookings/controllers/reservation/ReservationDetailsView.java new file mode 100644 index 0000000..762ba93 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/reservation/ReservationDetailsView.java @@ -0,0 +1,121 @@ +package com.github.mariosplen.bookings.controllers.reservation; + + +import com.github.mariosplen.bookings.models.Book; +import com.github.mariosplen.bookings.models.BookDAO; +import com.github.mariosplen.bookings.models.Guest; +import com.github.mariosplen.bookings.models.GuestDAO; +import com.github.mariosplen.bookings.util.Nav; +import com.github.mariosplen.bookings.util.Views; +import javafx.application.Platform; +import javafx.collections.FXCollections; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.TextField; +import javafx.scene.text.Text; +import javafx.stage.Stage; +import org.controlsfx.control.SearchableComboBox; + +import java.io.IOException; +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.List; +import java.util.stream.Collectors; + +public class ReservationDetailsView { + private final int numberOfNights; + private final int roomId; + private final LocalDate checkInDate; + private final LocalDate checkOutDate; + @FXML + private Text roomIDText, categoryText, numberOfNightsText, finalPriceText, errorMsg; + @FXML + private TextField doorPrice; + + @FXML + private SearchableComboBox usersSearchBox; + private int totalPrice; + + + public ReservationDetailsView(Book tempBook) throws SQLException, ClassNotFoundException { + roomId = tempBook.roomId(); + checkInDate = tempBook.checkIn(); + checkOutDate = tempBook.checkOut(); + + numberOfNights = checkInDate.until(checkOutDate).getDays(); + + + Platform.runLater(() -> { + + try { + setUsersInBox(); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + + numberOfNightsText.setText("Number of nights: " + numberOfNights); + roomIDText.setText("room ID: " + roomId); + + categoryText.setText(tempBook.roomCategory()); + + + }); + } + + @FXML + private void refresh() { + totalPrice = numberOfNights * Integer.parseInt(doorPrice.getText()); + finalPriceText.setText("$ " + totalPrice); + } + + private void setUsersInBox() throws SQLException, ClassNotFoundException { + List guestList = GuestDAO.getGuests(); + usersSearchBox.setItems( + FXCollections.observableArrayList(guestList.stream().map(Guest::name).collect(Collectors.toList())) + ); + } + + + public void onAddGuestBtnClicked() throws IOException { + FXMLLoader loader = new FXMLLoader(getClass().getResource(Views.NEW_GUEST)); + Stage popUpStage = new Stage(); + loader.load(); + Scene scene = new Scene(loader.getRoot()); + popUpStage.setScene(scene); + popUpStage.show(); + popUpStage.setOnCloseRequest(windowEvent -> { + try { + setUsersInBox(); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }); + } + + + public void onSubmitClicked() throws IOException, SQLException, ClassNotFoundException { + errorMsg.setVisible(false); + if (usersSearchBox.getValue() == null || totalPrice == 0) { + errorMsg.setText("Please enter correct parameters!"); + errorMsg.setVisible(true); + return; + } + + BookDAO.addBook( + roomId, + categoryText.getText(), + usersSearchBox.getValue(), + checkInDate, + checkOutDate, + LocalDate.now(), + totalPrice + ); + + Nav.toHome(); + } +} + + + + diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/reservation/ReservationView.java b/src/main/java/com/github/mariosplen/bookings/controllers/reservation/ReservationView.java new file mode 100644 index 0000000..2857e57 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/reservation/ReservationView.java @@ -0,0 +1,145 @@ +package com.github.mariosplen.bookings.controllers.reservation; + + +import com.github.mariosplen.bookings.models.Book; +import com.github.mariosplen.bookings.models.Room; +import com.github.mariosplen.bookings.models.RoomDAO; +import com.github.mariosplen.bookings.util.Nav; +import javafx.fxml.FXML; +import javafx.fxml.Initializable; +import javafx.scene.control.*; + +import java.io.IOException; +import java.net.URL; +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.List; +import java.util.ResourceBundle; + +public class ReservationView implements Initializable { + public ChoiceBox categoryChoiceBox; + @FXML + private Label errorLabel; + @FXML + private Button continueButton; + @FXML + private DatePicker checkInDP, checkOutDP; + private Book tempBook; + + private List availableRooms; + + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + + continueButton.setOnAction(actionEvent -> { + try { + Nav.toResDetails(tempBook); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + setDatePickers(); + + // Populate the categoryChoiceBox with category names from the database + fillCategoryChoiceBox(); + } + + + public void checkAvailabilityClicked() throws SQLException, ClassNotFoundException { + if (availableRooms != null) { + availableRooms.clear(); + } + + // Hide the continue button and error label initially + continueButton.setVisible(false); + errorLabel.setVisible(false); + + // Check that the check-in and check-out dates are not null + if (checkInDP.getValue() == null || checkOutDP.getValue() == null) { + errorLabel.setVisible(true); + errorLabel.setText("Error please enter valid parameters"); + return; + } + + // Get the selected category name + String cat; + if (categoryChoiceBox.getValue().equals("Single")) { + cat = "Single"; + } else if (categoryChoiceBox.getValue().equals("Twin")) { + cat = "Twin"; + } else if (categoryChoiceBox.getValue().equals("Double")) { + cat = "Double"; + } else { + // If the selected category is not recognized, show an error message + errorLabel.setVisible(true); + errorLabel.setText("Error please enter valid parameters"); + return; + } + // Get a list of available rooms that match the selected category and date range + availableRooms = RoomDAO.getAvailableForDate(checkInDP.getValue(), checkOutDP.getValue(), cat); + + if (availableRooms.size() > 0) { + // If at least one room is available, show the room's ID and enable the continue button + errorLabel.setText(String.format("Room Found with id: %s", availableRooms.get(0).id())); + Room foundRoom = availableRooms.get(0); + errorLabel.setVisible(true); + tempBook = new Book( + -1, + foundRoom.id(), + categoryChoiceBox.getValue(), + null, + checkInDP.getValue(), + checkOutDP.getValue(), + null, + 0 + ); + + + continueButton.setVisible(true); + } else { + // If no rooms are available, show an error message + errorLabel.setVisible(true); + errorLabel.setText("No rooms found!"); + } + } + + + private void fillCategoryChoiceBox() { + categoryChoiceBox.getItems().addAll( + "Double", "Single", "Twin" + ); + } + + private void setDatePickers() { + // Set the minimum date for check-in to be today + LocalDate start = LocalDate.now(); + + // Disable check-in dates that are before today or after the check-out date + checkInDP.setDayCellFactory(d -> new DateCell() { + @Override + public void updateItem(LocalDate item, boolean empty) { + super.updateItem(item, empty); + try { + setDisable(item.isBefore(start) || item.isAfter(checkOutDP.getValue().minusDays(1))); + } catch (Exception e) { + setDisable(item.isBefore(start)); + } + } + }); + + // Disable check-out dates that are before the check-in date + checkOutDP.setDayCellFactory(d -> new DateCell() { + @Override + public void updateItem(LocalDate item, boolean empty) { + super.updateItem(item, empty); + try { + setDisable(item.isBefore(checkInDP.getValue().plusDays(1))); + } catch (Exception e) { + setDisable(item.isBefore(LocalDate.now().plusDays(1))); + } + } + }); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/users/UserItem.java b/src/main/java/com/github/mariosplen/bookings/controllers/users/UserItem.java new file mode 100644 index 0000000..f1ad64e --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/users/UserItem.java @@ -0,0 +1,162 @@ +package com.github.mariosplen.bookings.controllers.users; + +import com.github.mariosplen.bookings.models.UserDAO; +import com.github.mariosplen.bookings.util.Nav; +import com.github.mariosplen.bookings.util.Views; +import javafx.event.ActionEvent; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.geometry.Insets; +import javafx.geometry.Pos; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.control.PasswordField; +import javafx.scene.control.Tooltip; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.BorderPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.VBox; +import javafx.scene.shape.Rectangle; +import javafx.scene.text.Text; +import javafx.stage.Stage; +import javafx.stage.Window; +import javafx.util.Duration; + +import java.io.IOException; +import java.net.URL; +import java.sql.SQLException; +import java.util.ResourceBundle; + +public class UserItem implements Initializable { + public Rectangle basicPerm; + public Rectangle manageGuests; + public Rectangle manageUsers; + public Text nameTxt; + + public void onChangePassBtnClicked(ActionEvent actionEvent) { + + // Finds current username by going backwards to the node tree + String username = ( + ((Text) + ((Button) actionEvent.getSource()) + .getParent().getChildrenUnmodifiable().get(3)) + .getText() + ); + + BorderPane borderPane = new BorderPane(); + Scene scene = new Scene(borderPane); + Stage stage = new Stage(); + stage.setScene(scene); + stage.setTitle("Change Password of User: " + username); + Label enterPass = new Label("Enter new Password"); + PasswordField passwordField = new PasswordField(); + passwordField.setStyle("-fx-background-color: #C6B3EF;\n" + + " -fx-background-radius: 3;"); + Button save = new Button("Save"); + save.setStyle(""" + -fx-background-color: #5100FC; + -fx-text-fill: #FFFFFF; + -fx-background-radius: 6; + -fx-font-size: 20; + -fx-font-weight: bold; + -fx-border-radius: 6; + -fx-border-color: #000000; + -fx-border-width: 1; + -fx-padding: 14;"""); + enterPass.setStyle("-fx-font-size: 32; -fx-font-weight: bold;"); + VBox vBox = new VBox(enterPass, passwordField, save); + vBox.setSpacing(20); + vBox.setPadding(new Insets(40)); + vBox.setAlignment(Pos.CENTER); + borderPane.setCenter(vBox); + stage.show(); + save.setOnAction(actionEvent1 -> { + try { + UserDAO.changePass(username, passwordField.getText()); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + stage.close(); + }); + + } + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + Tooltip basic = new Tooltip("Basic Functionality"); + basic.setShowDelay(Duration.ZERO); + Tooltip.install(basicPerm, basic); + Tooltip guestsManage = new Tooltip("Edit Guests"); + guestsManage.setShowDelay(Duration.ZERO); + Tooltip.install(manageGuests, guestsManage); + Tooltip usersManage = new Tooltip("Edit Users"); + usersManage.setShowDelay(Duration.ZERO); + Tooltip.install(manageUsers, usersManage); + + } + + public void onDeleteBtnClicked(ActionEvent actionEvent) throws SQLException, ClassNotFoundException { + String username = ( + ((Text) + ((Button) actionEvent.getSource()) + .getParent().getChildrenUnmodifiable().get(3)) + .getText() + ); + UserDAO.deleteUser(username); + refreshView(); + + } + + private void refreshView() throws SQLException, ClassNotFoundException { + // Refresh mainPane by re-creating loader + Window.getWindows().forEach(window -> { + Parent p = window.getScene().getRoot(); + // if it has mainPane that means that it's the main Screen + if (p.lookup("#contentPane") != null) { + FXMLLoader loader = new FXMLLoader(getClass().getResource(Views.USERS)); + try { + ((BorderPane) (p.lookup("#contentPane"))).setCenter(loader.load()); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + }); + + Nav.user = UserDAO.login(Nav.user.username(), Nav.user.password()); + } + + public void onPermManageUsersClicked(MouseEvent mouseEvent) throws SQLException, ClassNotFoundException { + + String username = handleRectangleClick(mouseEvent); + UserDAO.switchPerm(username, "manage_users"); + refreshView(); + } + + public void onPermManageGuestsClicked(MouseEvent mouseEvent) throws SQLException, ClassNotFoundException { + String username = handleRectangleClick(mouseEvent); + UserDAO.switchPerm(username, "manage_guests"); + refreshView(); + } + + + public void onPermBasicClicked(MouseEvent mouseEvent) throws SQLException, ClassNotFoundException { + String username = handleRectangleClick(mouseEvent); + UserDAO.switchPerm(username, "basic_functions"); + refreshView(); + } + + private String handleRectangleClick(MouseEvent event) { + // Get the rectangle that was clicked + Rectangle rectangle = (Rectangle) event.getSource(); + + // Get the HBox containing the rectangle + HBox hBox = (HBox) rectangle.getParent(); + + // Get the HBox containing the HBoxes + HBox allHBoxes = (HBox) hBox.getParent(); + + return ((Text) allHBoxes.getChildren().get(3)).getText(); + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/controllers/users/UsersView.java b/src/main/java/com/github/mariosplen/bookings/controllers/users/UsersView.java new file mode 100644 index 0000000..8a9ce33 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/controllers/users/UsersView.java @@ -0,0 +1,47 @@ +package com.github.mariosplen.bookings.controllers.users; + + +import com.github.mariosplen.bookings.models.UserDAO; +import com.github.mariosplen.bookings.util.Views; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.layout.VBox; +import javafx.scene.paint.Color; + +import java.io.IOException; +import java.net.URL; +import java.sql.SQLException; +import java.util.ResourceBundle; + +public class UsersView implements Initializable { + public VBox usersVBox; + + @Override + public void initialize(URL url, ResourceBundle resourceBundle) { + try { + UserDAO.getUsers().forEach(user -> { + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(Views.USER_ITEM)); + + try { + usersVBox.getChildren().add(fxmlLoader.load()); + UserItem userItem = fxmlLoader.getController(); + if (user.canManageUsers()) { + userItem.manageUsers.setFill(Color.web("0x5100FC", 1)); + } + if (user.canDoBasic()) { + userItem.basicPerm.setFill(Color.web("0x5100FC", 1)); + } + if (user.canManageGuests()) { + userItem.manageGuests.setFill(Color.web("0x5100FC", 1)); + } + userItem.nameTxt.setText(user.username()); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/src/main/java/com/github/mariosplen/bookings/models/Book.java b/src/main/java/com/github/mariosplen/bookings/models/Book.java new file mode 100644 index 0000000..9d68fb9 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/Book.java @@ -0,0 +1,15 @@ +package com.github.mariosplen.bookings.models; + +import java.time.LocalDate; + +public record Book( + int id, + int roomId, + String roomCategory, + String guestName, + LocalDate checkIn, + LocalDate checkOut, + LocalDate date, + int totalPrice +) { +} diff --git a/src/main/java/com/github/mariosplen/bookings/models/BookDAO.java b/src/main/java/com/github/mariosplen/bookings/models/BookDAO.java new file mode 100644 index 0000000..a0e04ed --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/BookDAO.java @@ -0,0 +1,105 @@ +package com.github.mariosplen.bookings.models; + +import com.github.mariosplen.bookings.util.DBManager; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class BookDAO { + + public static Map> getRoomBookDates() throws SQLException, ClassNotFoundException { + String query = "SELECT room_id, check_in, check_out FROM books;"; + + ResultSet rs = DBManager.dbExecuteQuery(query); + + Map> roomBookDates = new HashMap<>(); + while (rs.next()) { + LocalDate from = LocalDate.parse(rs.getString("check_in")); + LocalDate to = LocalDate.parse(rs.getString("check_out")); + List dates = new ArrayList<>(from.datesUntil(to).toList()); + dates.add(to); + + + if (roomBookDates.containsKey(rs.getInt("room_id"))) { + roomBookDates.get(rs.getInt("room_id")).addAll(dates); + } else { + roomBookDates.put(rs.getInt("room_id"), dates); + } + + + } + rs.close(); + return roomBookDates; + } + + + public static void addBook( + int roomId, + String roomCategory, + String guestName, + LocalDate checkIn, + LocalDate checkOut, + LocalDate date, + int totalPrice + ) throws SQLException, ClassNotFoundException { + String query = """ + INSERT INTO books(room_id, room_category, guest_name, check_in, check_out, date, total_price) + VALUES(?, ?, ?, ?, ?, ?, ?) + """; + DBManager.dbExecuteUpdate(query, + roomId, + roomCategory, + guestName, + checkIn, + checkOut, + date, + totalPrice + ); + + } + + public static ObservableList getBooks() throws SQLException, ClassNotFoundException { + String query = "SELECT * FROM books;"; + ResultSet rs = DBManager.dbExecuteQuery(query); + ObservableList books = getBooksFromRS(rs); + rs.close(); + + return books; + } + + public static Book getBookFromRs(ResultSet rs) throws SQLException { + return new Book( + rs.getInt("id"), + rs.getInt("room_id"), + rs.getString("room_category"), + rs.getString("guest_name"), + LocalDate.parse(rs.getString("check_in")), + LocalDate.parse(rs.getString("check_out")), + LocalDate.parse(rs.getString("date")), + rs.getInt("total_price") + ); + + } + + public static ObservableList getBooksFromRS(ResultSet rs) throws SQLException { + ObservableList books = FXCollections.observableArrayList(); + while (rs.next()) { + books.add(getBookFromRs(rs)); + } + return books; + } + + public static void deleteBook(int id) throws SQLException, ClassNotFoundException { + String query = "DELETE FROM books WHERE id = ? "; + DBManager.dbExecuteUpdate(query, id); + + } +} + diff --git a/src/main/java/com/github/mariosplen/bookings/models/Guest.java b/src/main/java/com/github/mariosplen/bookings/models/Guest.java new file mode 100644 index 0000000..3c45451 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/Guest.java @@ -0,0 +1,8 @@ +package com.github.mariosplen.bookings.models; + +public record Guest( + String name, + String phone, + String email +) { +} diff --git a/src/main/java/com/github/mariosplen/bookings/models/GuestDAO.java b/src/main/java/com/github/mariosplen/bookings/models/GuestDAO.java new file mode 100644 index 0000000..8b78e04 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/GuestDAO.java @@ -0,0 +1,58 @@ +package com.github.mariosplen.bookings.models; + + +import com.github.mariosplen.bookings.util.DBManager; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class GuestDAO { + + public static ObservableList getGuests() throws SQLException, ClassNotFoundException { + String query = "SELECT * FROM guests"; + ResultSet rs = DBManager.dbExecuteQuery(query); + + ObservableList guests = getGuestsFromRs(rs); + rs.close(); + return guests; + } + + + public static Guest getGuestFromRs(ResultSet rs) throws SQLException { + return new Guest( + rs.getString("name"), + rs.getString("phone"), + rs.getString("email")); + } + + public static ObservableList getGuestsFromRs(ResultSet rs) throws SQLException { + ObservableList guests = FXCollections.observableArrayList(); + while (rs.next()) { + guests.add(getGuestFromRs(rs)); + } + return guests; + } + + + public static void addGuest(String name, String phone, String email) throws SQLException, ClassNotFoundException { + String query = """ + INSERT INTO guests(name, phone, email) + VALUES(?,?,?) + """; + DBManager.dbExecuteUpdate(query, name, phone, email); + + } + + public static void updateData(String name, String perm, String value) throws SQLException, ClassNotFoundException { + + String query = """ + UPDATE guests SET '%s' = ? + WHERE name = ? + """.formatted(perm); + DBManager.dbExecuteUpdate(query, value, name); + + } + +} diff --git a/src/main/java/com/github/mariosplen/bookings/models/Room.java b/src/main/java/com/github/mariosplen/bookings/models/Room.java new file mode 100644 index 0000000..2c500f9 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/Room.java @@ -0,0 +1,7 @@ +package com.github.mariosplen.bookings.models; + +public record Room( + int id, + String category +) { +} diff --git a/src/main/java/com/github/mariosplen/bookings/models/RoomDAO.java b/src/main/java/com/github/mariosplen/bookings/models/RoomDAO.java new file mode 100644 index 0000000..f530287 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/RoomDAO.java @@ -0,0 +1,70 @@ +package com.github.mariosplen.bookings.models; + + +import com.github.mariosplen.bookings.util.DBManager; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.List; + +public class RoomDAO { + + public static ObservableList getRooms() throws SQLException, ClassNotFoundException { + String query = "SELECT * FROM rooms"; + ResultSet rs = DBManager.dbExecuteQuery(query); + + ObservableList rooms = getRoomsFromRs(rs); + rs.close(); + return rooms; + } + + + public static Room getRoomFromRs(ResultSet rs) throws SQLException { + return new Room( + rs.getInt("id"), + rs.getString("category") + ); + } + + public static ObservableList getRoomsFromRs(ResultSet rs) throws SQLException { + ObservableList rooms = FXCollections.observableArrayList(); + while (rs.next()) { + rooms.add(getRoomFromRs(rs)); + } + return rooms; + } + + public static List getAvailableForDate(LocalDate checkIn, LocalDate checkOut, String cat) throws SQLException, ClassNotFoundException { + + + String query = """ + SELECT * FROM rooms r + WHERE r.category = ? + AND r.id NOT IN ( + SELECT b.room_id FROM books b + WHERE (b.check_in <= ? AND b.check_out >= ? ) + OR (b.check_in <= ? AND b.check_out >= ? ) + OR (b.check_in >= ? AND b.check_out <= ? ) + ) + """; + + + ResultSet rs = DBManager.dbExecuteQuery(query, + cat, + checkIn.toString(), + checkOut.toString(), + checkOut.toString(), + checkIn.toString(), + checkIn.toString(), + checkOut.toString() + ); + List rooms = getRoomsFromRs(rs); + rs.close(); + return rooms; + + } + +} diff --git a/src/main/java/com/github/mariosplen/bookings/models/SettingsDAO.java b/src/main/java/com/github/mariosplen/bookings/models/SettingsDAO.java new file mode 100644 index 0000000..a9b8751 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/SettingsDAO.java @@ -0,0 +1,24 @@ +package com.github.mariosplen.bookings.models; + +import com.github.mariosplen.bookings.util.DBManager; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class SettingsDAO { + public static String getHotelKey() throws SQLException, ClassNotFoundException { + String query = "SELECT value FROM settings WHERE name = 'hotel_key'"; + ResultSet rs = DBManager.dbExecuteQuery(query); + + String key = getKeyFromRS(rs); + rs.close(); + return key; + } + + private static String getKeyFromRS(ResultSet rs) throws SQLException { + if (rs.next()) { + return rs.getString("value"); + } + return null; + } +} diff --git a/src/main/java/com/github/mariosplen/bookings/models/User.java b/src/main/java/com/github/mariosplen/bookings/models/User.java new file mode 100644 index 0000000..e996888 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/User.java @@ -0,0 +1,10 @@ +package com.github.mariosplen.bookings.models; + +public record User( + String username, + String password, + Boolean canDoBasic, + Boolean canManageGuests, + Boolean canManageUsers +) { +} \ No newline at end of file diff --git a/src/main/java/com/github/mariosplen/bookings/models/UserDAO.java b/src/main/java/com/github/mariosplen/bookings/models/UserDAO.java new file mode 100644 index 0000000..7aba285 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/models/UserDAO.java @@ -0,0 +1,91 @@ +package com.github.mariosplen.bookings.models; + +import com.github.mariosplen.bookings.util.DBManager; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +import java.sql.ResultSet; +import java.sql.SQLException; + +public class UserDAO { + + + public static ObservableList getUsers() throws SQLException, ClassNotFoundException { + String query = "SELECT * FROM users"; + ResultSet rs = DBManager.dbExecuteQuery(query); + + ObservableList users = getUsersFromRS(rs); + rs.close(); + return users; + } + + public static User login(String username, String password) throws SQLException, ClassNotFoundException { + String query = "SELECT * FROM users WHERE username = ? AND password = ?"; + ResultSet rs = DBManager.dbExecuteQuery(query, username, password); + + if (rs.next()) { + User user = getUserFromRs(rs); + rs.close(); + return user; + } + rs.close(); + return null; + + } + + public static void changePass(String username, String newPass) throws SQLException, ClassNotFoundException { + String query = "UPDATE users SET password = ? WHERE username = ? "; + DBManager.dbExecuteUpdate(query, newPass, username); + } + + private static User getUserFromRs(ResultSet rs) throws SQLException { + return new User( + rs.getString("username"), + rs.getString("password"), + rs.getBoolean("basic_functions"), + rs.getBoolean("manage_guests"), + rs.getBoolean("manage_users") + ); + } + + private static ObservableList getUsersFromRS(ResultSet rs) throws SQLException { + ObservableList users = FXCollections.observableArrayList(); + while (rs.next()) { + users.add(getUserFromRs(rs)); + } + return users; + } + + public static void addUser( + String username, + String password, + Boolean canDoBasic, + Boolean canManageGuests, + Boolean canManageUsers + ) throws SQLException, ClassNotFoundException { + String query = """ + INSERT INTO users(username, password, basic_functions, manage_guests, manage_users) + VALUES(?,?,?,?,?) + """; + DBManager.dbExecuteUpdate(query, + username, + password, + canDoBasic, + canManageGuests, + canManageUsers + ); + + } + + public static void deleteUser(String username) throws SQLException, ClassNotFoundException { + String query = "DELETE FROM users WHERE username = ? "; + DBManager.dbExecuteUpdate(query, username); + } + + public static void switchPerm(String username, String perm) throws SQLException, ClassNotFoundException { + + String query = "UPDATE `users` SET %s = (( %s | 1) - ( %s & 1)) WHERE username = ? ".formatted(perm, perm, perm); + + DBManager.dbExecuteUpdate(query, username); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/mariosplen/bookings/util/DBManager.java b/src/main/java/com/github/mariosplen/bookings/util/DBManager.java new file mode 100644 index 0000000..3f72331 --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/util/DBManager.java @@ -0,0 +1,66 @@ +package com.github.mariosplen.bookings.util; + +import javax.sql.rowset.CachedRowSet; +import javax.sql.rowset.RowSetProvider; +import java.sql.*; + +public class DBManager { + private static final String JDBC_DRIVER = "org.sqlite.JDBC"; + private static final String connStr = "jdbc:sqlite:assets/database/bookings.db"; + private static Connection conn = null; + + private static void dbConnect() throws SQLException, ClassNotFoundException { + Class.forName(JDBC_DRIVER); + conn = DriverManager.getConnection(connStr); + } + + private static void dbDisconnect() throws SQLException { + if (conn != null && !conn.isClosed()) { + conn.close(); + } + } + + public static ResultSet dbExecuteQuery( + String query, Object... varArgs + ) throws SQLException, ClassNotFoundException { + dbConnect(); + PreparedStatement ps = conn.prepareStatement(query); + + // Sets the value of every designated parameter + for (int i = 0; i < varArgs.length; i++) { + ps.setObject(i + 1, varArgs[i]); + } + + ResultSet rs = ps.executeQuery(); + + CachedRowSet crs = RowSetProvider.newFactory().createCachedRowSet(); + crs.populate(rs); + + if (rs != null) { + rs.close(); + } + + ps.close(); + dbDisconnect(); + return crs; + } + + + public static void dbExecuteUpdate( + String query, Object... varArgs + ) throws SQLException, ClassNotFoundException { + dbConnect(); + PreparedStatement ps = conn.prepareStatement(query); + + // Sets the value of every designated parameter + for (int i = 0; i < varArgs.length; i++) { + ps.setObject(i + 1, varArgs[i]); + } + + ps.executeUpdate(); + + ps.close(); + dbDisconnect(); + } + +} \ No newline at end of file diff --git a/src/main/java/com/github/mariosplen/bookings/util/Nav.java b/src/main/java/com/github/mariosplen/bookings/util/Nav.java new file mode 100644 index 0000000..ef00adb --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/util/Nav.java @@ -0,0 +1,146 @@ +package com.github.mariosplen.bookings.util; + + +import com.github.mariosplen.bookings.controllers.MainView; +import com.github.mariosplen.bookings.controllers.reservation.ReservationDetailsView; +import com.github.mariosplen.bookings.models.Book; +import com.github.mariosplen.bookings.models.User; +import javafx.fxml.FXMLLoader; +import javafx.scene.Node; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.image.Image; +import javafx.scene.layout.BorderPane; +import javafx.stage.Stage; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Objects; + +public class Nav { + private static Stage stage; + public static BorderPane content; + public static Button backBtn; + public static User user; + + public static void toLoading(Stage stage) throws IOException { + Nav.stage = stage; + FXMLLoader fxmlLoader = new FXMLLoader(Nav.class.getResource(Views.LOADING)); + Nav.stage.setScene(new Scene(fxmlLoader.load())); + // Set the icon of the stage + stage.getIcons().add(new Image(Objects.requireNonNull(Nav.class.getResource("/com/github/mariosplen/bookings/media/icons/icon.png")).toExternalForm())); + + // Set the title of the stage + stage.setTitle("Hotel Reservation Management"); + + // Make the stage non-resizable, because of intro video + stage.setResizable(false); + + // Show the stage + stage.show(); + } + + public static void toLogin() throws IOException { + FXMLLoader fxmlLoader = new FXMLLoader(Nav.class.getResource(Views.LOGIN)); + stage.setScene(new Scene(fxmlLoader.load())); + + // Set the stage to be resizable again + stage.setResizable(true); + + // Set the minimum dimensions for the stage + stage.setMinHeight(600); + stage.setMinWidth(800); + } + + public static void toRegister() throws IOException { + FXMLLoader contentLoader = new FXMLLoader(Nav.class.getResource(Views.REGISTER)); + Node content = contentLoader.load(); + + FXMLLoader fxmlLoader = new FXMLLoader(Nav.class.getResource(Views.MAIN)); + fxmlLoader.setControllerFactory(aClass -> new MainView(null, content)); + stage.setScene(new Scene(fxmlLoader.load())); + + + } + + public static void toRecovery() throws IOException { + FXMLLoader contentLoader = new FXMLLoader(Nav.class.getResource(Views.RECOVERY)); + + stage.setScene(new Scene(contentLoader.load())); + } + + public static void toHome() throws IOException { + FXMLLoader contentLoader = new FXMLLoader(Nav.class.getResource(Views.HOME)); + + FXMLLoader loader = new FXMLLoader(Nav.class.getResource(Views.MAIN)); + + loader.setControllerFactory(controllerClass -> { + try { + return new MainView(user, contentLoader.load()); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + + + stage.setScene(new Scene(loader.load())); + MainView mainViewController = loader.getController(); + backBtn = mainViewController.getBackBtn(); + backBtn.setVisible(false); + Nav.content = mainViewController.contentPane; + } + + public static void toCalendar() throws IOException { + FXMLLoader contentLoader = new FXMLLoader(Nav.class.getResource(Views.CALENDAR)); + content.setCenter(contentLoader.load()); + backBtn.setVisible(true); + } + + + public static void toNewGuest() throws IOException { + FXMLLoader contentLoader = new FXMLLoader(Nav.class.getResource(Views.NEW_GUEST)); + content.setCenter(contentLoader.load()); + backBtn.setVisible(true); + } + + public static void toUsers() throws IOException { + FXMLLoader contentLoader = new FXMLLoader(Nav.class.getResource(Views.USERS)); + content.setCenter(contentLoader.load()); + backBtn.setVisible(true); + } + + public static void toGuests() throws IOException { + FXMLLoader contentLoader = new FXMLLoader(Nav.class.getResource(Views.GUESTS)); + content.setCenter(contentLoader.load()); + backBtn.setVisible(true); + } + + public static void toReservation() throws IOException { + FXMLLoader contentLoader = new FXMLLoader(Nav.class.getResource(Views.RESERVATION)); + content.setCenter(contentLoader.load()); + backBtn.setVisible(true); + } + + public static void toResDetails(Book tempBook) throws IOException { + FXMLLoader loader = new FXMLLoader(Nav.class.getResource(Views.RESERVATION_DETAILS)); + loader.setControllerFactory(controllerClass -> { + try { + return new ReservationDetailsView(tempBook); + } catch (SQLException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + }); + content.setCenter(loader.load()); + backBtn.setVisible(true); + } + + + public static void toBooks() throws IOException { + FXMLLoader loader = new FXMLLoader(Nav.class.getResource(Views.BOOKS)); + content.setCenter(loader.load()); + backBtn.setVisible(true); + } + + + +} diff --git a/src/main/java/com/github/mariosplen/bookings/util/ReceiptGenerator.java b/src/main/java/com/github/mariosplen/bookings/util/ReceiptGenerator.java new file mode 100644 index 0000000..ac1e99b --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/util/ReceiptGenerator.java @@ -0,0 +1,149 @@ +package com.github.mariosplen.bookings.util; + +import javafx.stage.FileChooser; +import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.PDPage; +import org.apache.pdfbox.pdmodel.PDPageContentStream; +import org.apache.pdfbox.pdmodel.font.PDType1Font; + +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +public class ReceiptGenerator { + + + + public void genReceipt( + String name, LocalDate dateOfArrivalLD, LocalDate dateOfDepartureLD, int total + ) throws IOException { + + String dateOfArrival = dateOfArrivalLD.format(DateTimeFormatter.ofPattern("EEEE, MMM dd yyyy").withLocale(Locale.ENGLISH)); + String dateOfDeparture = dateOfDepartureLD.format(DateTimeFormatter.ofPattern("EEEE, MMM dd yyyy").withLocale(Locale.ENGLISH)); + int days = dateOfArrivalLD.until(dateOfDepartureLD).getDays(); + + + PDDocument document = new PDDocument(); + PDPage page = new PDPage(); + document.addPage(page); + + + //first page + PDPage page1 = document.getPage(0); + + //initialisation of content stream + PDPageContentStream cs = new PDPageContentStream(document, page1); + + cs.beginText(); + cs.setFont(PDType1Font.HELVETICA_BOLD, 40); + cs.setNonStrokingColor(Color.getColor("5100FC")); + cs.newLineAtOffset(75, 700); + cs.showText("HOTELINO"); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 28); + cs.setNonStrokingColor(Color.black); + cs.newLineAtOffset(100, 675); + cs.showText("Invoice"); + cs.endText(); + + + java.util.Date date = new java.util.Date(); + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(400, 675); + cs.showText("" + date); + cs.endText(); + + + // Predetermined text + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(100, 590); + cs.showText("Name:"); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(100, 570); + cs.showText("Date of arrival:"); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(100, 550); + cs.showText("Date of departure:"); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(100, 530); + cs.showText("Length of stay:"); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 20); + cs.setNonStrokingColor(Color.getColor("5100FC")); + cs.newLineAtOffset(100, 210); + cs.showText("Total:"); + cs.setNonStrokingColor(Color.black); + cs.endText(); + + + // Dynamic data + + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(250, 590); + cs.showText(name); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(250, 570); + cs.showText(dateOfArrival); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(250, 550); + cs.showText(dateOfDeparture); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 14); + cs.newLineAtOffset(250, 530); + cs.showText("" + days); + cs.endText(); + + cs.beginText(); + cs.setFont(PDType1Font.TIMES_ROMAN, 21); + cs.setNonStrokingColor(Color.getColor("5100FC")); + cs.newLineAtOffset(250, 210); + cs.showText(total + "€"); + cs.setNonStrokingColor(Color.black); + cs.endText(); + + + cs.close(); + + + // Save the pdf + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Save"); + fileChooser.getExtensionFilters().addAll(new FileChooser.ExtensionFilter("All Files", "*.*")); + + File dir = fileChooser.showSaveDialog(Nav.content.getScene().getWindow()); + String directory = dir + String.valueOf(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC)) + ".pdf"; + document.save(directory); + + + } +} \ No newline at end of file diff --git a/src/main/java/com/github/mariosplen/bookings/util/Views.java b/src/main/java/com/github/mariosplen/bookings/util/Views.java new file mode 100644 index 0000000..a45d6cb --- /dev/null +++ b/src/main/java/com/github/mariosplen/bookings/util/Views.java @@ -0,0 +1,22 @@ +package com.github.mariosplen.bookings.util; + +public class Views { + public static final String MAIN = "/com/github/mariosplen/bookings/fxml/main-view.fxml"; + + + public static final String BOOKS = "/com/github/mariosplen/bookings/fxml/books/books-view.fxml"; + public static final String CALENDAR = "/com/github/mariosplen/bookings/fxml/calendar/calendar-view.fxml"; + public static final String GUESTS = "/com/github/mariosplen/bookings/fxml/guests/guests-view.fxml"; + public static final String HOME = "/com/github/mariosplen/bookings/fxml/home/home-view.fxml"; + public static final String LOADING = "/com/github/mariosplen/bookings/fxml/loading/loading-view.fxml"; + public static final String LOGIN = "/com/github/mariosplen/bookings/fxml/login/login-view.fxml"; + public static final String REGISTER = "/com/github/mariosplen/bookings/fxml/register/register-view.fxml"; + public static final String RESERVATION = "/com/github/mariosplen/bookings/fxml/reservation/reservation-view.fxml"; + public static final String USER_ITEM = "/com/github/mariosplen/bookings/fxml/users/user-item.fxml"; + public static final String USERS = "/com/github/mariosplen/bookings/fxml/users/users-view.fxml"; + public static final String RECOVERY = "/com/github/mariosplen/bookings/fxml/recovery/recovery-view.fxml"; + public static final String NEW_GUEST = "/com/github/mariosplen/bookings/fxml/new-guest/new-guest-view.fxml"; + public static final String RESERVATION_DETAILS = "/com/github/mariosplen/bookings/fxml/reservation/reservation-details-view.fxml"; +} + + diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java new file mode 100644 index 0000000..45272bf --- /dev/null +++ b/src/main/java/module-info.java @@ -0,0 +1,42 @@ +module com.github.mariosplen.bookings { + requires javafx.controls; + requires javafx.fxml; + requires java.sql; + requires javafx.media; + requires java.sql.rowset; + requires org.controlsfx.controls; + requires java.desktop; + requires org.apache.pdfbox; + requires org.xerial.sqlitejdbc; + + exports com.github.mariosplen.bookings.controllers; + exports com.github.mariosplen.bookings; + exports com.github.mariosplen.bookings.models; + exports com.github.mariosplen.bookings.util; + exports com.github.mariosplen.bookings.controllers.books; + exports com.github.mariosplen.bookings.controllers.calendar; + exports com.github.mariosplen.bookings.controllers.home; + exports com.github.mariosplen.bookings.controllers.register; + exports com.github.mariosplen.bookings.controllers.recovery; + exports com.github.mariosplen.bookings.controllers.users; + exports com.github.mariosplen.bookings.controllers.loading; + exports com.github.mariosplen.bookings.controllers.reservation; + exports com.github.mariosplen.bookings.controllers.guests; + exports com.github.mariosplen.bookings.controllers.new_guest; + + opens com.github.mariosplen.bookings.controllers to javafx.fxml; + opens com.github.mariosplen.bookings to javafx.fxml; + opens com.github.mariosplen.bookings.models to javafx.fxml; + opens com.github.mariosplen.bookings.util to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.books to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.calendar to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.recovery to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.home to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.new_guest to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.login to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.register to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.users to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.loading to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.reservation to javafx.fxml; + opens com.github.mariosplen.bookings.controllers.guests to javafx.fxml; +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/mariosplen/bookings/HelloApplication.kt b/src/main/kotlin/com/github/mariosplen/bookings/HelloApplication.kt deleted file mode 100644 index 2b680e3..0000000 --- a/src/main/kotlin/com/github/mariosplen/bookings/HelloApplication.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.github.mariosplen.bookings - -import javafx.application.Application -import javafx.fxml.FXMLLoader -import javafx.scene.Scene -import javafx.stage.Stage - -class HelloApplication : Application() { - override fun start(stage: Stage) { - val fxmlLoader = FXMLLoader(HelloApplication::class.java.getResource("hello-view.fxml")) - val scene = Scene(fxmlLoader.load(), 320.0, 240.0) - stage.title = "Hello!" - stage.scene = scene - stage.show() - } -} - -fun main() { - Application.launch(HelloApplication::class.java) -} \ No newline at end of file diff --git a/src/main/kotlin/com/github/mariosplen/bookings/HelloController.kt b/src/main/kotlin/com/github/mariosplen/bookings/HelloController.kt deleted file mode 100644 index 2a3247b..0000000 --- a/src/main/kotlin/com/github/mariosplen/bookings/HelloController.kt +++ /dev/null @@ -1,13 +0,0 @@ -package bookings - -import javafx.fxml.FXML -import javafx.scene.control.Label - -class HelloController { - @FXML - private lateinit var welcomeText: Label - - fun onHelloButtonClick() { - welcomeText.text = "Welcome to JavaFX Application!" - } -} \ No newline at end of file diff --git a/src/main/kotlin/module-info.java b/src/main/kotlin/module-info.java deleted file mode 100644 index 3ccadfe..0000000 --- a/src/main/kotlin/module-info.java +++ /dev/null @@ -1,9 +0,0 @@ -module com.github.mariosplen.bookings { - requires javafx.controls; - requires javafx.fxml; - requires kotlin.stdlib; - - - opens com.github.mariosplen.bookings to javafx.fxml; - exports com.github.mariosplen.bookings; -} \ No newline at end of file diff --git a/src/main/resources/com/github/mariosplen/bookings/bookings.css b/src/main/resources/com/github/mariosplen/bookings/bookings.css new file mode 100644 index 0000000..2637851 --- /dev/null +++ b/src/main/resources/com/github/mariosplen/bookings/bookings.css @@ -0,0 +1,386 @@ +@font-face { + src: url("fonts/Solway/Solway-Bold.ttf"); +} + +.hotelinoTitle { + -fx-font-family: 'Atomic Age'; + -fx-font-size: 96 +} + +.mainViewUsername { + -fx-fill: #FFF; + -fx-font-family: Solway; + -fx-font-size: 30; + -fx-font-weight: bold +} + +.header { + -fx-font-family: Solway; + -fx-font-size: 40; + -fx-font-weight: bold +} + +.mediumText { + -fx-font-family: Solway; + -fx-font-size: 20; + -fx-font-weight: bold +} + +.smallText { + -fx-font-family: Solway; + -fx-font-size: 15; + -fx-font-weight: bold +} + +.errorText { + -fx-fill: #FF1212; + -fx-font-family: Solway; + -fx-font-size: 15; + -fx-font-weight: bold +} + +.bigBtn { + -fx-background-color: #5100FC; + -fx-background-radius: 32; + -fx-font-family: Solway; + -fx-font-size: 40; + -fx-font-weight: bold; + -fx-padding: 0; + -fx-text-fill: #FFF +} + +.mediumBtn { + -fx-background-color: #5100FC; + -fx-background-radius: 6; + -fx-font-family: Solway; + -fx-font-size: 32; + -fx-font-weight: bold; + -fx-padding: 0; + -fx-text-fill: #FFF +} + +.smallBtn { + -fx-background-color: #5100FC; + -fx-background-radius: 6; + -fx-font-family: Solway; + -fx-font-size: 20; + -fx-font-weight: bold; + -fx-padding: 14; + -fx-text-fill: #FFF +} + +/*noinspection CssUnusedSymbol*/ +.verySmallBtn { + -fx-background-color: #5100FC; + -fx-background-radius: 3; + -fx-font-family: Solway; + -fx-font-size: 12; + -fx-font-weight: bold; + -fx-text-fill: #FFF +} + +.smallBtnRed { + -fx-background-color: #ff3636; + -fx-background-radius: 6; + -fx-font-family: Solway; + -fx-font-size: 20; + -fx-font-weight: bold; + -fx-padding: 14; + -fx-text-fill: #FFF +} + +/*noinspection CssUnusedSymbol*/ +.verySmallRedBtn { + -fx-background-color: #ff3636; + -fx-background-radius: 3; + -fx-font-family: Solway; + -fx-font-size: 12; + -fx-font-weight: bold; + -fx-text-fill: #FFF +} + +.mediumBtn:disabled { + -fx-background-color: #696969; + -fx-opacity: 1 +} + +.calendarLeftBtn { + -fx-background-radius: 0 0 0 6; + -fx-font-size: 24; + -fx-font-weight: normal +} + +.calendarRightBtn { + -fx-background-radius: 0 0 6 0; + -fx-font-size: 24; + -fx-font-weight: normal +} + +.basicTF { + -fx-background-color: #C6B3EF; + -fx-background-radius: 3; + -fx-font-size: 24 +} + +/*noinspection CssUnusedSymbol*/ +.basicTF:hover, .basicTF:focused, .choice-box .menu-item:focused, .choice-box:hover { + -fx-background-color: #D1C2F2 +} + +.logoutHBox:hover, .backButton:hover { + -fx-background-color: #e9f5f9 +} + +.checkBox { + -fx-font-size: 24; + -fx-text-fill: #000 +} + +/*noinspection CssUnusedSymbol*/ +.checkBox .box { + -fx-background-color: #D9D9D9; + -fx-background-radius: 0; + -fx-border-width: 0 +} + +/*noinspection CssUnusedSymbol*/ +.checkBox:hover .box { + -fx-background-color: #E6E6E6 +} + +.designPane { + -fx-background-color: #C6B3EF; + -fx-background-radius: 3 +} + +.choice-box { + -fx-background-color: #C6B3EF; + -fx-font-size: 24px; + -fx-mark-color: #000 +} + +/*noinspection CssUnusedSymbol*/ +.choice-box .context-menu { + -fx-background-color: #C6B3EF +} + +.choice-box .menu-item > .label { + -fx-text-fill: #FFF +} + +.choice-box .menu-item:focused > .label, .choice-box .label { + -fx-text-fill: #000 +} + +.date-picker { + -fx-background-color: #5100FC; + -fx-focus-color: -fx-secondary-color; + -fx-font-size: 24px; + -fx-light-grey-color: #d1d1d1; + -fx-primary-color: #5100FC; + -fx-secondary-color: #5100FC +} + +/*noinspection CssUnusedSymbol*/ +.date-picker .arrow-button { + -fx-background-color: -fx-primary-color; + -fx-background-radius: 0 +} + +/*noinspection CssUnusedSymbol*/ +.date-picker .arrow-button .arrow, .date-picker .cell { + -fx-background-color: #fff +} + +/*noinspection CssUnusedSymbol*/ +.date-picker .arrow-button:hover { + -fx-background-color: #784ae3 +} + +/*noinspection CssUnusedSymbol*/ +.date-picker .cell:hover, .date-picker .cell:focused, .date-picker-popup .month-year-pane { + -fx-background-color: -fx-primary-color +} + +/*noinspection CssUnusedSymbol*/ +.date-picker .selected, .date-picker .selected:focused { + -fx-background-color: -fx-primary-color; + -fx-text-fill: #fff +} + +/*noinspection CssUnusedSymbol*/ +.date-picker-popup { + -fx-border-color: transparent +} + +.date-picker-popup .month-year-pane .label { + -fx-text-fill: #fff +} + +/*noinspection CssUnusedSymbol*/ +.date-picker-popup .spinner .button .left-arrow, .date-picker-popup .spinner .button .right-arrow { + -fx-background-color: -fx-secondary-color +} + +/*noinspection CssUnusedSymbol*/ +.date-picker-popup .week-number-cell { + -fx-text-fill: -fx-secondary-color +} + +.permissionsBoxesBackground { + -fx-background-color: #D9D9D9 +} + +/*noinspection CssUnusedSymbol*/ +.scroll-bar:horizontal .thumb, .scroll-bar:vertical .thumb { + -fx-background-color: #5100FC; + -fx-background-radius: 5em +} + +/*noinspection CssUnusedSymbol*/ +.scroll-bar:horizontal .track, .scroll-bar:vertical .track { + -fx-background-color: transparent; + -fx-background-radius: 0; + -fx-border-color: transparent +} + +/*noinspection CssUnusedSymbol*/ +.scroll-pane { + -fx-background-color: #B3A5D1; + -fx-background-radius: 8 +} + +/*noinspection CssUnusedSymbol*/ +.scroll-pane .menu-item { + -fx-border-color: transparent; + -fx-border-style: solid +} + +/*noinspection CssUnusedSymbol*/ +.scroll-pane .scroll-arrow { + -fx-padding: 0 0 0 0 +} + +/*noinspection CssUnusedSymbol*/ +.scroll-pane > .corner { + -fx-background-color: #B3A5D1 +} + +/*noinspection CssUnusedSymbol*/ +.calendarCell { + -fx-fill: #C6B3EF +} + +/*noinspection CssUnusedSymbol*/ +.calendarCell:disabled { + -fx-border-width: 0; + -fx-effect: innershadow(gaussian, #000, 2, 0, 0, 0); + -fx-fill: #6100FF; + -fx-opacity: 1; + -fx-stroke-width: 0 +} + +/*noinspection CssUnusedSymbol*/ +.calendarCell:disabled:hover { + -fx-fill: #711BFF +} + +/*noinspection CssUnusedSymbol*/ +.calendarCell:hover { + -fx-fill: #D3C2F6 +} + +/*noinspection CssUnusedSymbol*/ +.calendarCellTagBlack { + -fx-background-color: #F7F7F7; + -fx-font-size: 22px; + -fx-text-fill: #000 +} + +/*noinspection CssUnusedSymbol*/ +.calendarCellTagWhite { + -fx-background-color: #5100FC; + -fx-font-size: 22px; + -fx-text-fill: #FFF +} + +/*noinspection CssUnusedSymbol*/ +.table-view .column-header-background { + -fx-background-color: linear-gradient(to bottom, rgba(81, 0, 252, 0.27), #C6B3EF44); + -fx-background-insets: 0 11px 0 0; + -fx-background-radius: 7px 7px 0 0; + -fx-padding: 0 0 5px 0 +} + +/*noinspection CssUnusedSymbol*/ +.table-view .table-cell { + -fx-border-color: transparent; + -fx-padding: 2 0 2 10px +} + +/*noinspection CssUnusedSymbol*/ +.table-row-cell:hover { + -fx-background-color: #93f9b911; + -fx-text-background-color: red +} + +/*noinspection CssUnusedSymbol*/ +.table-row-cell:odd { + -fx-background-color: #93f9b911; + -fx-background-insets: 0, 0 0 1 0; + -fx-padding: 0 +} + +/*noinspection CssUnusedSymbol*/ +.table-row-cell:even { + -fx-background-color: #1dbbdd11; + -fx-background-insets: 0, 0 0 1 0; + -fx-padding: 0 +} + +/*noinspection CssUnusedSymbol*/ +.table-view .virtual-flow .scroll-bar .increment-button, .table-view .virtual-flow .scroll-bar .decrement-button { + -fx-opacity: 0; + -fx-padding: 2 +} + +/*noinspection CssUnusedSymbol*/ +.table-view .virtual-flow .scroll-bar:vertical .thumb { + -fx-background-color: linear-gradient(to bottom, #1dbbdd44, #93f9b944) +} + +/*noinspection CssUnusedSymbol*/ +.table-view .virtual-flow .scroll-bar:horizontal .thumb { + -fx-background-color: linear-gradient(to right, #1dbbdd44, #93f9b944) +} + +/*noinspection CssUnusedSymbol*/ +.table-row-cell:selected { + -fx-background-color: #81c483; + -fx-background-radius: 15px +} + +/*noinspection CssUnusedSymbol*/ +.mainView, .blueBackground, .bigButton:pressed, .mediumBtn:pressed, .smallBtn:pressed, .check-box:selected .mark { + -fx-background-color: #5100FC +} + +/*noinspection CssUnusedSymbol*/ +.smallBtnRed:hover, .verySmallRedBtn:hover { + -fx-background-color: #ff4c4c +} + +/*noinspection CssUnusedSymbol*/ +.bigButton:hover, .mediumBtn:hover, .smallBtn:hover, .verySmallBtn:hover { + -fx-background-color: #7332FC +} + +.contentPane, .backButton { + -fx-background-color: #FFF; + -fx-background-radius: 16 +} + +/*noinspection CssUnusedSymbol*/ +.scroll-bar:horizontal, .scroll-bar:vertical, .table-view, .table-view .column-header-background .filler, .table-view .corner, .table-view .column-header, .table-view .virtual-flow .scroll-bar:vertical, .table-view .virtual-flow .scroll-bar:vertical .track, .table-view .virtual-flow .scroll-bar:vertical .track-background, .table-view .virtual-flow .scroll-bar:horizontal, .table-view .virtual-flow .scroll-bar:horizontal .track, .table-view .virtual-flow .scroll-bar:horizontal .track-background { + -fx-background-color: transparent +} \ No newline at end of file diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/AtomicAge-Regular.ttf b/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/AtomicAge-Regular.ttf new file mode 100644 index 0000000..fb8f824 Binary files /dev/null and b/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/AtomicAge-Regular.ttf differ diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/OFL.txt b/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/OFL.txt new file mode 100644 index 0000000..b0c2f04 --- /dev/null +++ b/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/OFL.txt @@ -0,0 +1,93 @@ +Copyright (c) 2013 - 2016, Sorkin Type Co (www.sorkintype.com) with Reserved Font Name 'Atomic Age'. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/atomic_age.css b/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/atomic_age.css new file mode 100644 index 0000000..0dba506 --- /dev/null +++ b/src/main/resources/com/github/mariosplen/bookings/fonts/AtomicAge/atomic_age.css @@ -0,0 +1,3 @@ +@font-face { + src: url("AtomicAge-Regular.ttf"); +} \ No newline at end of file diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/OFL.txt b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/OFL.txt new file mode 100644 index 0000000..a51be44 --- /dev/null +++ b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/OFL.txt @@ -0,0 +1,93 @@ +Copyright 2018 The Solway Project Authors (https://github.com/mashavp/Solway) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Bold.ttf b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Bold.ttf new file mode 100644 index 0000000..283ab55 Binary files /dev/null and b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Bold.ttf differ diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-ExtraBold.ttf b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-ExtraBold.ttf new file mode 100644 index 0000000..e6c86e5 Binary files /dev/null and b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-ExtraBold.ttf differ diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Light.ttf b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Light.ttf new file mode 100644 index 0000000..a1e7bc8 Binary files /dev/null and b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Light.ttf differ diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Medium.ttf b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Medium.ttf new file mode 100644 index 0000000..7ab6d00 Binary files /dev/null and b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Medium.ttf differ diff --git a/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Regular.ttf b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Regular.ttf new file mode 100644 index 0000000..3ef963c Binary files /dev/null and b/src/main/resources/com/github/mariosplen/bookings/fonts/Solway/Solway-Regular.ttf differ diff --git a/src/main/resources/com/github/mariosplen/bookings/fxml/books/books-view.fxml b/src/main/resources/com/github/mariosplen/bookings/fxml/books/books-view.fxml new file mode 100644 index 0000000..40b31be --- /dev/null +++ b/src/main/resources/com/github/mariosplen/bookings/fxml/books/books-view.fxml @@ -0,0 +1,29 @@ + + + + + + + + + + diff --git a/src/main/resources/com/github/mariosplen/bookings/fxml/calendar/calendar-view.fxml b/src/main/resources/com/github/mariosplen/bookings/fxml/calendar/calendar-view.fxml new file mode 100644 index 0000000..4e01fb2 --- /dev/null +++ b/src/main/resources/com/github/mariosplen/bookings/fxml/calendar/calendar-view.fxml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/com/github/mariosplen/bookings/fxml/guests/guests-view.fxml b/src/main/resources/com/github/mariosplen/bookings/fxml/guests/guests-view.fxml new file mode 100644 index 0000000..2061457 --- /dev/null +++ b/src/main/resources/com/github/mariosplen/bookings/fxml/guests/guests-view.fxml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/com/github/mariosplen/bookings/fxml/new-guest/new-guest-view.fxml b/src/main/resources/com/github/mariosplen/bookings/fxml/new-guest/new-guest-view.fxml new file mode 100644 index 0000000..febce68 --- /dev/null +++ b/src/main/resources/com/github/mariosplen/bookings/fxml/new-guest/new-guest-view.fxml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + +