Add DELETE key and Enter-to-confirm to all tables
This commit is contained in:
@@ -13,6 +13,7 @@ import javafx.stage.Stage;
|
|||||||
import org.example.petshopdesktop.controllers.dialogcontrollers.AdoptionDialogController;
|
import org.example.petshopdesktop.controllers.dialogcontrollers.AdoptionDialogController;
|
||||||
import org.example.petshopdesktop.database.AdoptionDB;
|
import org.example.petshopdesktop.database.AdoptionDB;
|
||||||
import org.example.petshopdesktop.models.Adoption;
|
import org.example.petshopdesktop.models.Adoption;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -80,6 +81,15 @@ public class AdoptionController {
|
|||||||
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
displayFilteredAdoptions(newValue);
|
displayFilteredAdoptions(newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//EventListener for DELETE key
|
||||||
|
tvAdoptions.setOnKeyPressed(event -> {
|
||||||
|
if (event.getCode() == javafx.scene.input.KeyCode.DELETE) {
|
||||||
|
if (tvAdoptions.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
btnDeleteClicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -96,6 +106,7 @@ public class AdoptionController {
|
|||||||
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
question.setHeaderText("Please confirm delete");
|
question.setHeaderText("Please confirm delete");
|
||||||
question.setContentText("Are you sure you want to delete this adoption record?");
|
question.setContentText("Are you sure you want to delete this adoption record?");
|
||||||
|
question.getDialogPane().lookupButton(ButtonType.OK).requestFocus();
|
||||||
Optional<ButtonType> result = question.showAndWait();
|
Optional<ButtonType> result = question.showAndWait();
|
||||||
|
|
||||||
if (result.isPresent() && result.get() == ButtonType.OK) {
|
if (result.isPresent() && result.get() == ButtonType.OK) {
|
||||||
@@ -105,12 +116,20 @@ public class AdoptionController {
|
|||||||
numRows = AdoptionDB.deleteAdoption(adoptionId);
|
numRows = AdoptionDB.deleteAdoption(adoptionId);
|
||||||
}
|
}
|
||||||
catch (SQLIntegrityConstraintViolationException e) {
|
catch (SQLIntegrityConstraintViolationException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"AdoptionController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting adoption (integrity constraint violation) with ID: " + adoptionId);
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
alert.setHeaderText("Database Operation Error");
|
alert.setHeaderText("Database Operation Error");
|
||||||
alert.setContentText("Delete failed\nThe selected adoption is being referred in another table");
|
alert.setContentText("Delete failed\nThe selected adoption is being referred in another table");
|
||||||
alert.showAndWait();
|
alert.showAndWait();
|
||||||
return;
|
return;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"AdoptionController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting adoption with ID: " + adoptionId);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +171,10 @@ public class AdoptionController {
|
|||||||
tvAdoptions.setItems(data);
|
tvAdoptions.setItems(data);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"AdoptionController.displayFilteredAdoptions",
|
||||||
|
e,
|
||||||
|
"Filtering adoptions with filter: " + filter);
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,6 +184,10 @@ public class AdoptionController {
|
|||||||
try {
|
try {
|
||||||
data = AdoptionDB.getAdoptions();
|
data = AdoptionDB.getAdoptions();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"AdoptionController.displayAdoptions",
|
||||||
|
e,
|
||||||
|
"Fetching adoption data for table display");
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
tvAdoptions.setItems(data);
|
tvAdoptions.setItems(data);
|
||||||
@@ -173,6 +200,10 @@ public class AdoptionController {
|
|||||||
try {
|
try {
|
||||||
scene = new Scene(fxmlLoader.load());
|
scene = new Scene(fxmlLoader.load());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"AdoptionController.openDialog",
|
||||||
|
e,
|
||||||
|
"Loading adoption dialog in " + mode + " mode");
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.example.petshopdesktop.controllers;
|
|||||||
|
|
||||||
import javafx.collections.FXCollections;
|
import javafx.collections.FXCollections;
|
||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.collections.transformation.FilteredList;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
@@ -14,6 +15,7 @@ import javafx.stage.Stage;
|
|||||||
import org.example.petshopdesktop.DTOs.AppointmentDTO;
|
import org.example.petshopdesktop.DTOs.AppointmentDTO;
|
||||||
import org.example.petshopdesktop.controllers.dialogcontrollers.AppointmentDialogController;
|
import org.example.petshopdesktop.controllers.dialogcontrollers.AppointmentDialogController;
|
||||||
import org.example.petshopdesktop.database.AppointmentDB;
|
import org.example.petshopdesktop.database.AppointmentDB;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
public class AppointmentController {
|
public class AppointmentController {
|
||||||
|
|
||||||
@@ -33,7 +35,8 @@ public class AppointmentController {
|
|||||||
|
|
||||||
@FXML private TextField txtSearch;
|
@FXML private TextField txtSearch;
|
||||||
|
|
||||||
private ObservableList<AppointmentDTO> data = FXCollections.observableArrayList();
|
private final ObservableList<AppointmentDTO> appointments = FXCollections.observableArrayList();
|
||||||
|
private FilteredList<AppointmentDTO> filtered;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize(){
|
public void initialize(){
|
||||||
@@ -46,18 +49,63 @@ public class AppointmentController {
|
|||||||
colCustomerName.setCellValueFactory(new PropertyValueFactory<>("customerName"));
|
colCustomerName.setCellValueFactory(new PropertyValueFactory<>("customerName"));
|
||||||
colAppointmentStatus.setCellValueFactory(new PropertyValueFactory<>("appointmentStatus"));
|
colAppointmentStatus.setCellValueFactory(new PropertyValueFactory<>("appointmentStatus"));
|
||||||
|
|
||||||
|
filtered = new FilteredList<>(appointments, a -> true);
|
||||||
|
tvAppointments.setItems(filtered);
|
||||||
|
|
||||||
|
if (txtSearch != null) {
|
||||||
|
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
//EventListener for DELETE key
|
||||||
|
tvAppointments.setOnKeyPressed(event -> {
|
||||||
|
if (event.getCode() == javafx.scene.input.KeyCode.DELETE) {
|
||||||
|
if (tvAppointments.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
btnDeleteClicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
loadAppointments();
|
loadAppointments();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadAppointments(){
|
private void loadAppointments(){
|
||||||
try{
|
try{
|
||||||
data = AppointmentDB.getAppointmentDTOs();
|
appointments.setAll(AppointmentDB.getAppointmentDTOs());
|
||||||
tvAppointments.setItems(data);
|
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"AppointmentController.loadAppointments",
|
||||||
|
e,
|
||||||
|
"Loading appointments for table display");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyFilter(String text) {
|
||||||
|
if (filtered == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String q = text == null ? "" : text.trim().toLowerCase();
|
||||||
|
if (q.isEmpty()) {
|
||||||
|
filtered.setPredicate(a -> true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered.setPredicate(a ->
|
||||||
|
String.valueOf(a.getAppointmentId()).contains(q)
|
||||||
|
|| safe(a.getPetName()).contains(q)
|
||||||
|
|| safe(a.getServiceName()).contains(q)
|
||||||
|
|| safe(a.getAppointmentDate()).contains(q)
|
||||||
|
|| safe(a.getAppointmentTime()).contains(q)
|
||||||
|
|| safe(a.getCustomerName()).contains(q)
|
||||||
|
|| safe(a.getAppointmentStatus()).contains(q)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String safe(String v) {
|
||||||
|
return v == null ? "" : v.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
void btnAddClicked(ActionEvent event){
|
void btnAddClicked(ActionEvent event){
|
||||||
openDialog(null, "Add");
|
openDialog(null, "Add");
|
||||||
@@ -89,6 +137,10 @@ public class AppointmentController {
|
|||||||
AppointmentDB.deleteAppointment(selected.getAppointmentId());
|
AppointmentDB.deleteAppointment(selected.getAppointmentId());
|
||||||
loadAppointments();
|
loadAppointments();
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"AppointmentController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting appointment with ID: " + selected.getAppointmentId());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,6 +173,10 @@ public class AppointmentController {
|
|||||||
loadAppointments();
|
loadAppointments();
|
||||||
|
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"AppointmentController.openDialog",
|
||||||
|
e,
|
||||||
|
"Opening appointment dialog in " + mode + " mode");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import javafx.stage.Stage;
|
|||||||
import org.example.petshopdesktop.controllers.dialogcontrollers.InventoryDialogController;
|
import org.example.petshopdesktop.controllers.dialogcontrollers.InventoryDialogController;
|
||||||
import org.example.petshopdesktop.database.InventoryDB;
|
import org.example.petshopdesktop.database.InventoryDB;
|
||||||
import org.example.petshopdesktop.models.Inventory;
|
import org.example.petshopdesktop.models.Inventory;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -79,6 +80,15 @@ public class InventoryController {
|
|||||||
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
displayFilteredInventory(newValue);
|
displayFilteredInventory(newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//EventListener for DELETE key
|
||||||
|
tvInventory.setOnKeyPressed(event -> {
|
||||||
|
if (event.getCode() == javafx.scene.input.KeyCode.DELETE) {
|
||||||
|
if (tvInventory.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
btnDeleteClicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Opens dialog in add mode
|
//Opens dialog in add mode
|
||||||
@@ -98,6 +108,7 @@ public class InventoryController {
|
|||||||
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
question.setHeaderText("Please confirm delete");
|
question.setHeaderText("Please confirm delete");
|
||||||
question.setContentText("Are you sure you want to delete this inventory record?");
|
question.setContentText("Are you sure you want to delete this inventory record?");
|
||||||
|
question.getDialogPane().lookupButton(ButtonType.OK).requestFocus();
|
||||||
Optional<ButtonType> result = question.showAndWait();
|
Optional<ButtonType> result = question.showAndWait();
|
||||||
|
|
||||||
//If user confirms, proceed with trying to delete...
|
//If user confirms, proceed with trying to delete...
|
||||||
@@ -109,6 +120,10 @@ public class InventoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
catch (SQLIntegrityConstraintViolationException e) {
|
catch (SQLIntegrityConstraintViolationException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"InventoryController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting inventory (integrity constraint violation) with ID: " + inventoryId);
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
alert.setHeaderText("Database Operation Error");
|
alert.setHeaderText("Database Operation Error");
|
||||||
alert.setContentText("Delete failed\nThe selected inventory record is being referred in another table");
|
alert.setContentText("Delete failed\nThe selected inventory record is being referred in another table");
|
||||||
@@ -117,6 +132,10 @@ public class InventoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"InventoryController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting inventory with ID: " + inventoryId);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +189,10 @@ public class InventoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"InventoryController.displayFilteredInventory",
|
||||||
|
e,
|
||||||
|
"Filtering inventory with filter: " + filter);
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -182,6 +205,10 @@ public class InventoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"InventoryController.displayInventory",
|
||||||
|
e,
|
||||||
|
"Fetching inventory data for table display");
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
tvInventory.setItems(data);
|
tvInventory.setItems(data);
|
||||||
@@ -198,6 +225,10 @@ public class InventoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
catch (IOException e) {
|
catch (IOException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"InventoryController.openDialog",
|
||||||
|
e,
|
||||||
|
"Loading inventory dialog in " + mode + " mode");
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,20 +4,20 @@ import javafx.event.ActionEvent;
|
|||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.control.Label;
|
import javafx.scene.control.Label;
|
||||||
import javafx.scene.control.PasswordField;
|
import javafx.scene.control.PasswordField;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.stage.Modality;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.example.petshopdesktop.auth.UserSession;
|
import org.example.petshopdesktop.auth.UserSession;
|
||||||
|
import org.example.petshopdesktop.database.ConnectionDB;
|
||||||
import org.example.petshopdesktop.database.UserDB;
|
import org.example.petshopdesktop.database.UserDB;
|
||||||
import org.example.petshopdesktop.models.User;
|
import org.example.petshopdesktop.models.User;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
|
||||||
/*
|
|
||||||
Petshop Desktop
|
|
||||||
Purpose: Authentication controller responsible for validating credentials and initialising the user session.
|
|
||||||
*/
|
|
||||||
public class LoginController {
|
public class LoginController {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
@@ -29,20 +29,34 @@ public class LoginController {
|
|||||||
@FXML
|
@FXML
|
||||||
private Label lblError;
|
private Label lblError;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Button btnCreateStaff;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void initialize() {
|
||||||
|
lblError.setText("");
|
||||||
|
try {
|
||||||
|
ConnectionDB.getConnection().close();
|
||||||
|
try {
|
||||||
|
UserDB.initializeTable();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
lblError.setText("Database is not connected. Check Docker and connectionpetstore.properties.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
void btnLoginClicked(ActionEvent event) {
|
void btnLoginClicked(ActionEvent event) {
|
||||||
// Input normalisation keeps authentication behaviour consistent.
|
|
||||||
String username = txtUsername.getText().trim();
|
String username = txtUsername.getText().trim();
|
||||||
String password = txtPassword.getText();
|
String password = txtPassword.getText();
|
||||||
|
|
||||||
// Basic validation to avoid unnecessary database calls.
|
|
||||||
if (username.isEmpty() || password.isEmpty()) {
|
if (username.isEmpty() || password.isEmpty()) {
|
||||||
lblError.setText("Please enter username and password.");
|
lblError.setText("Please enter username and password.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Credential verification returns a fully populated User on success.
|
|
||||||
User user = UserDB.authenticate(username, password);
|
User user = UserDB.authenticate(username, password);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
lblError.setText("Invalid username or password.");
|
lblError.setText("Invalid username or password.");
|
||||||
@@ -50,18 +64,55 @@ public class LoginController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Session state is stored in memory for use by controllers and UI RBAC.
|
UserSession.getInstance().login(
|
||||||
UserSession.getInstance().login(user.getUsername(), user.getRole());
|
user.getUserId(),
|
||||||
|
user.getEmployeeId(),
|
||||||
|
user.getUsername(),
|
||||||
|
user.getEmployeeFullName(),
|
||||||
|
user.getRole()
|
||||||
|
);
|
||||||
openMainLayout();
|
openMainLayout();
|
||||||
|
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
lblError.setText("Database error: " + e.getMessage());
|
ActivityLogger.getInstance().logException(
|
||||||
|
"LoginController.btnLoginClicked",
|
||||||
|
e,
|
||||||
|
"Authentication attempt for username: " + username);
|
||||||
|
String msg = e.getMessage() == null ? "" : e.getMessage().toLowerCase();
|
||||||
|
if (msg.contains("doesn't exist") || msg.contains("unknown database") || msg.contains("access denied")) {
|
||||||
|
lblError.setText("Database error. Check Docker and connectionpetstore.properties.");
|
||||||
|
} else {
|
||||||
|
lblError.setText("Login failed. Check username and password.");
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"LoginController.btnLoginClicked",
|
||||||
|
e,
|
||||||
|
"Database connection");
|
||||||
|
lblError.setText("Database is not connected. Check Docker and connectionpetstore.properties.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
void btnCreateStaffClicked(ActionEvent event) {
|
||||||
|
lblError.setText("");
|
||||||
|
try {
|
||||||
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/staff-register-dialog-view.fxml"));
|
||||||
|
Stage dialog = new Stage();
|
||||||
|
dialog.initOwner(txtUsername.getScene().getWindow());
|
||||||
|
dialog.initModality(Modality.APPLICATION_MODAL);
|
||||||
|
dialog.setTitle("Create Staff Account");
|
||||||
|
dialog.setScene(new Scene(loader.load()));
|
||||||
|
dialog.setResizable(false);
|
||||||
|
dialog.showAndWait();
|
||||||
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException("LoginController.btnCreateStaffClicked", e, "Opening staff register dialog");
|
||||||
|
lblError.setText("Could not open staff account creation.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openMainLayout() {
|
private void openMainLayout() {
|
||||||
try {
|
try {
|
||||||
// View transition into the post login application shell.
|
|
||||||
FXMLLoader loader = new FXMLLoader(
|
FXMLLoader loader = new FXMLLoader(
|
||||||
getClass().getResource("/org/example/petshopdesktop/main-layout-view.fxml"));
|
getClass().getResource("/org/example/petshopdesktop/main-layout-view.fxml"));
|
||||||
Scene scene = new Scene(loader.load());
|
Scene scene = new Scene(loader.load());
|
||||||
@@ -69,6 +120,10 @@ public class LoginController {
|
|||||||
stage.setScene(scene);
|
stage.setScene(scene);
|
||||||
stage.setTitle("Pet Shop Manager");
|
stage.setTitle("Pet Shop Manager");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"LoginController.openMainLayout",
|
||||||
|
e,
|
||||||
|
"Loading main application layout after successful login");
|
||||||
lblError.setText("Error loading application: " + e.getMessage());
|
lblError.setText("Error loading application: " + e.getMessage());
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.example.petshopdesktop.controllers.dialogcontrollers.PetDialogControl
|
|||||||
import org.example.petshopdesktop.database.PetDB;
|
import org.example.petshopdesktop.database.PetDB;
|
||||||
import org.example.petshopdesktop.database.ProductDB;
|
import org.example.petshopdesktop.database.ProductDB;
|
||||||
import org.example.petshopdesktop.models.Pet;
|
import org.example.petshopdesktop.models.Pet;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -73,6 +74,7 @@ public class PetController {
|
|||||||
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
question.setHeaderText("Please confirm delete");
|
question.setHeaderText("Please confirm delete");
|
||||||
question.setContentText("Are you sure you want to delete this pet?");
|
question.setContentText("Are you sure you want to delete this pet?");
|
||||||
|
question.getDialogPane().lookupButton(ButtonType.OK).requestFocus();
|
||||||
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
||||||
|
|
||||||
//if confirmed,start deletion
|
//if confirmed,start deletion
|
||||||
@@ -84,6 +86,10 @@ public class PetController {
|
|||||||
numRows = PetDB.deletePet(petId);
|
numRows = PetDB.deletePet(petId);
|
||||||
}
|
}
|
||||||
catch (SQLIntegrityConstraintViolationException e){
|
catch (SQLIntegrityConstraintViolationException e){
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"PetController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting pet (integrity constraint violation) with ID: " + petId);
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
alert.setHeaderText("Database Operation Error");
|
alert.setHeaderText("Database Operation Error");
|
||||||
alert.setContentText("Delete failed\n" +
|
alert.setContentText("Delete failed\n" +
|
||||||
@@ -92,6 +98,10 @@ public class PetController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"PetController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting pet with ID: " + petId);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +164,15 @@ public class PetController {
|
|||||||
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
displayFilteredPet(newValue);
|
displayFilteredPet(newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//EventListener for DELETE key
|
||||||
|
tvPets.setOnKeyPressed(event -> {
|
||||||
|
if (event.getCode() == javafx.scene.input.KeyCode.DELETE) {
|
||||||
|
if (tvPets.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
btnDeleteClicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayFilteredPet(String filter) {
|
private void displayFilteredPet(String filter) {
|
||||||
@@ -167,6 +186,10 @@ public class PetController {
|
|||||||
tvPets.setItems(data);
|
tvPets.setItems(data);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"PetController.displayFilteredPet",
|
||||||
|
e,
|
||||||
|
"Filtering pets with filter: " + filter);
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,6 +201,10 @@ public class PetController {
|
|||||||
data = PetDB.getPets();
|
data = PetDB.getPets();
|
||||||
}
|
}
|
||||||
catch(SQLException e){
|
catch(SQLException e){
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"PetController.displayPets",
|
||||||
|
e,
|
||||||
|
"Fetching pet data for table display");
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,6 +218,10 @@ public class PetController {
|
|||||||
try{
|
try{
|
||||||
scene = new Scene(fxmlLoader.load());
|
scene = new Scene(fxmlLoader.load());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"PetController.openDialog",
|
||||||
|
e,
|
||||||
|
"Loading pet dialog in " + mode + " mode");
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
PetDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
PetDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.example.petshopdesktop.database.ProductDB;
|
|||||||
import org.example.petshopdesktop.database.SupplierDB;
|
import org.example.petshopdesktop.database.SupplierDB;
|
||||||
import org.example.petshopdesktop.models.Product;
|
import org.example.petshopdesktop.models.Product;
|
||||||
import org.example.petshopdesktop.models.Supplier;
|
import org.example.petshopdesktop.models.Supplier;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -92,6 +93,15 @@ public class ProductController {
|
|||||||
displayFilteredProduct(newValue);
|
displayFilteredProduct(newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//EventListener for DELETE key press
|
||||||
|
tvProducts.setOnKeyPressed(event -> {
|
||||||
|
if (event.getCode() == javafx.scene.input.KeyCode.DELETE) {
|
||||||
|
if (tvProducts.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
btnDeleteClicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,6 +116,10 @@ public class ProductController {
|
|||||||
data = ProductDB.getProductDTO();
|
data = ProductDB.getProductDTO();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductController.displayProduct",
|
||||||
|
e,
|
||||||
|
"Fetching product data for table display");
|
||||||
}
|
}
|
||||||
|
|
||||||
//put data in the table
|
//put data in the table
|
||||||
@@ -136,6 +150,7 @@ public class ProductController {
|
|||||||
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
question.setHeaderText("Please confirm delete");
|
question.setHeaderText("Please confirm delete");
|
||||||
question.setContentText("Are you sure you want to delete this product?");
|
question.setContentText("Are you sure you want to delete this product?");
|
||||||
|
question.getDialogPane().lookupButton(ButtonType.OK).requestFocus();
|
||||||
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
||||||
|
|
||||||
//if confirmed,start deletion
|
//if confirmed,start deletion
|
||||||
@@ -147,6 +162,10 @@ public class ProductController {
|
|||||||
numRows = ProductDB.deleteProduct(prodId);
|
numRows = ProductDB.deleteProduct(prodId);
|
||||||
}
|
}
|
||||||
catch (SQLIntegrityConstraintViolationException e){
|
catch (SQLIntegrityConstraintViolationException e){
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
String.format("Attempting to delete product ID %d - foreign key constraint", prodId));
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
alert.setHeaderText("Database Operation Error");
|
alert.setHeaderText("Database Operation Error");
|
||||||
alert.setContentText("Delete failed\n" +
|
alert.setContentText("Delete failed\n" +
|
||||||
@@ -155,6 +174,10 @@ public class ProductController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
String.format("Attempting to delete product ID %d", prodId));
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,6 +235,10 @@ public class ProductController {
|
|||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductController.displayFilteredProduct",
|
||||||
|
e,
|
||||||
|
String.format("Filtering products with keyword: %s", filter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +255,10 @@ public class ProductController {
|
|||||||
try{
|
try{
|
||||||
scene = new Scene(fxmlLoader.load());
|
scene = new Scene(fxmlLoader.load());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductController.openDialog",
|
||||||
|
e,
|
||||||
|
String.format("Loading product dialog view in %s mode", mode));
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
ProductDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
ProductDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.example.petshopdesktop.controllers.dialogcontrollers.ProductSupplierD
|
|||||||
import org.example.petshopdesktop.database.ProductDB;
|
import org.example.petshopdesktop.database.ProductDB;
|
||||||
import org.example.petshopdesktop.database.ProductSupplierDB;
|
import org.example.petshopdesktop.database.ProductSupplierDB;
|
||||||
import org.example.petshopdesktop.models.ProductSupplier;
|
import org.example.petshopdesktop.models.ProductSupplier;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -89,6 +90,15 @@ public class ProductSupplierController {
|
|||||||
displayFilteredProductSupplier(newValue);
|
displayFilteredProductSupplier(newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//EventListener for DELETE key
|
||||||
|
tvProductSuppliers.setOnKeyPressed(event -> {
|
||||||
|
if (event.getCode() == javafx.scene.input.KeyCode.DELETE) {
|
||||||
|
if (tvProductSuppliers.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
btnDeleteClicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -102,6 +112,10 @@ public class ProductSupplierController {
|
|||||||
try{
|
try{
|
||||||
data = ProductSupplierDB.getProductSupplierDTO();
|
data = ProductSupplierDB.getProductSupplierDTO();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductSupplierController.displayProductSupplier",
|
||||||
|
e,
|
||||||
|
"Fetching product-supplier data for table display");
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +139,10 @@ public class ProductSupplierController {
|
|||||||
tvProductSuppliers.setItems(data);
|
tvProductSuppliers.setItems(data);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductSupplierController.displayFilteredProductSupplier",
|
||||||
|
e,
|
||||||
|
"Filtering product-supplier data with filter: " + filter);
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,6 +171,7 @@ public class ProductSupplierController {
|
|||||||
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
question.setHeaderText("Please confirm delete");
|
question.setHeaderText("Please confirm delete");
|
||||||
question.setContentText("Are you sure you want to delete this product-supplier?");
|
question.setContentText("Are you sure you want to delete this product-supplier?");
|
||||||
|
question.getDialogPane().lookupButton(ButtonType.OK).requestFocus();
|
||||||
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
||||||
|
|
||||||
//if confirmed,start deletion
|
//if confirmed,start deletion
|
||||||
@@ -165,6 +184,10 @@ public class ProductSupplierController {
|
|||||||
numRows = ProductSupplierDB.deleteProductSupplier(supId, prodId);
|
numRows = ProductSupplierDB.deleteProductSupplier(supId, prodId);
|
||||||
}
|
}
|
||||||
catch (SQLIntegrityConstraintViolationException e){
|
catch (SQLIntegrityConstraintViolationException e){
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductSupplierController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting product-supplier (integrity constraint violation) - SupID: " + supId + ", ProdID: " + prodId);
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
alert.setHeaderText("Database Operation Error");
|
alert.setHeaderText("Database Operation Error");
|
||||||
alert.setContentText("Delete failed\n" +
|
alert.setContentText("Delete failed\n" +
|
||||||
@@ -173,6 +196,10 @@ public class ProductSupplierController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductSupplierController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting product-supplier - SupID: " + supId + ", ProdID: " + prodId);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +249,10 @@ public class ProductSupplierController {
|
|||||||
try{
|
try{
|
||||||
scene = new Scene(fxmlLoader.load());
|
scene = new Scene(fxmlLoader.load());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ProductSupplierController.openDialog",
|
||||||
|
e,
|
||||||
|
"Loading product-supplier dialog in " + mode + " mode");
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
ProductSupplierDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
ProductSupplierDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
package org.example.petshopdesktop.controllers;
|
package org.example.petshopdesktop.controllers;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.collections.transformation.FilteredList;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.cell.PropertyValueFactory;
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
import org.example.petshopdesktop.DTOs.PurchaseOrderDTO;
|
import org.example.petshopdesktop.DTOs.PurchaseOrderDTO;
|
||||||
import org.example.petshopdesktop.database.PurchaseOrderDB;
|
import org.example.petshopdesktop.database.PurchaseOrderDB;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
public class PurchaseOrderController {
|
public class PurchaseOrderController {
|
||||||
|
|
||||||
@FXML private Button btnRefresh;
|
@FXML private Button btnRefresh;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextField txtSearch;
|
||||||
|
|
||||||
@FXML private TableView<PurchaseOrderDTO> tvPurchaseOrders;
|
@FXML private TableView<PurchaseOrderDTO> tvPurchaseOrders;
|
||||||
|
|
||||||
@FXML private TableColumn<PurchaseOrderDTO,Integer> colOrderId;
|
@FXML private TableColumn<PurchaseOrderDTO,Integer> colOrderId;
|
||||||
@@ -17,6 +24,9 @@ public class PurchaseOrderController {
|
|||||||
@FXML private TableColumn<PurchaseOrderDTO,String> colOrderDate;
|
@FXML private TableColumn<PurchaseOrderDTO,String> colOrderDate;
|
||||||
@FXML private TableColumn<PurchaseOrderDTO,String> colStatus;
|
@FXML private TableColumn<PurchaseOrderDTO,String> colStatus;
|
||||||
|
|
||||||
|
private final ObservableList<PurchaseOrderDTO> purchaseOrders = FXCollections.observableArrayList();
|
||||||
|
private FilteredList<PurchaseOrderDTO> filtered;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
|
||||||
@@ -32,21 +42,53 @@ public class PurchaseOrderController {
|
|||||||
colStatus.setCellValueFactory(
|
colStatus.setCellValueFactory(
|
||||||
new PropertyValueFactory<>("status"));
|
new PropertyValueFactory<>("status"));
|
||||||
|
|
||||||
|
filtered = new FilteredList<>(purchaseOrders, p -> true);
|
||||||
|
tvPurchaseOrders.setItems(filtered);
|
||||||
|
|
||||||
|
if (txtSearch != null) {
|
||||||
|
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
||||||
|
}
|
||||||
|
|
||||||
loadPurchaseOrders();
|
loadPurchaseOrders();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadPurchaseOrders() {
|
private void loadPurchaseOrders() {
|
||||||
try {
|
try {
|
||||||
tvPurchaseOrders.setItems(
|
purchaseOrders.setAll(PurchaseOrderDB.getPurchaseOrders());
|
||||||
PurchaseOrderDB.getPurchaseOrders()
|
|
||||||
);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"PurchaseOrderController.loadPurchaseOrders",
|
||||||
|
e,
|
||||||
|
"Loading purchase orders for table display");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
new Alert(Alert.AlertType.ERROR,
|
new Alert(Alert.AlertType.ERROR,
|
||||||
"Unable to load purchase orders").showAndWait();
|
"Unable to load purchase orders").showAndWait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyFilter(String text) {
|
||||||
|
if (filtered == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String q = text == null ? "" : text.trim().toLowerCase();
|
||||||
|
if (q.isEmpty()) {
|
||||||
|
filtered.setPredicate(p -> true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered.setPredicate(p ->
|
||||||
|
String.valueOf(p.getPurchaseOrderId()).contains(q)
|
||||||
|
|| safe(p.getSupplierName()).contains(q)
|
||||||
|
|| safe(p.getOrderDate()).contains(q)
|
||||||
|
|| safe(p.getStatus()).contains(q)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String safe(String v) {
|
||||||
|
return v == null ? "" : v.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
void btnRefresh() {
|
void btnRefresh() {
|
||||||
loadPurchaseOrders();
|
loadPurchaseOrders();
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
package org.example.petshopdesktop.controllers;
|
package org.example.petshopdesktop.controllers;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.collections.transformation.FilteredList;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.fxml.FXMLLoader;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.Parent;
|
|
||||||
import javafx.scene.Node;
|
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.*;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.input.MouseEvent;
|
|
||||||
import javafx.scene.control.cell.PropertyValueFactory;
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.example.petshopdesktop.database.ServiceDB;
|
import org.example.petshopdesktop.database.ServiceDB;
|
||||||
import org.example.petshopdesktop.models.Service;
|
import org.example.petshopdesktop.models.Service;
|
||||||
import org.example.petshopdesktop.controllers.dialogcontrollers.ServiceDialogController;
|
import org.example.petshopdesktop.controllers.dialogcontrollers.ServiceDialogController;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
|
|
||||||
|
|
||||||
@@ -32,6 +33,9 @@ public class ServiceController {
|
|||||||
|
|
||||||
@FXML private TextField txtSearch;
|
@FXML private TextField txtSearch;
|
||||||
|
|
||||||
|
private final ObservableList<Service> services = FXCollections.observableArrayList();
|
||||||
|
private FilteredList<Service> filtered;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
|
||||||
@@ -41,18 +45,62 @@ public class ServiceController {
|
|||||||
colServiceDuration.setCellValueFactory(new PropertyValueFactory<>("serviceDuration"));
|
colServiceDuration.setCellValueFactory(new PropertyValueFactory<>("serviceDuration"));
|
||||||
colServicePrice.setCellValueFactory(new PropertyValueFactory<>("servicePrice"));
|
colServicePrice.setCellValueFactory(new PropertyValueFactory<>("servicePrice"));
|
||||||
|
|
||||||
|
filtered = new FilteredList<>(services, s -> true);
|
||||||
|
tvServices.setItems(filtered);
|
||||||
|
|
||||||
|
if (txtSearch != null) {
|
||||||
|
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
||||||
|
}
|
||||||
|
|
||||||
|
//EventListener for DELETE key
|
||||||
|
tvServices.setOnKeyPressed(event -> {
|
||||||
|
if (event.getCode() == javafx.scene.input.KeyCode.DELETE) {
|
||||||
|
if (tvServices.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
btnDeleteClicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
loadServices();
|
loadServices();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadServices() {
|
private void loadServices() {
|
||||||
try {
|
try {
|
||||||
tvServices.setItems(ServiceDB.getServices());
|
services.setAll(ServiceDB.getServices());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ServiceController.loadServices",
|
||||||
|
e,
|
||||||
|
"Loading services for table display");
|
||||||
showAlert("Database Error", "Unable to load services.");
|
showAlert("Database Error", "Unable to load services.");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyFilter(String text) {
|
||||||
|
if (filtered == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String q = text == null ? "" : text.trim().toLowerCase();
|
||||||
|
if (q.isEmpty()) {
|
||||||
|
filtered.setPredicate(s -> true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered.setPredicate(s ->
|
||||||
|
String.valueOf(s.getServiceId()).contains(q)
|
||||||
|
|| safe(s.getServiceName()).contains(q)
|
||||||
|
|| safe(s.getServiceDesc()).contains(q)
|
||||||
|
|| String.valueOf(s.getServiceDuration()).contains(q)
|
||||||
|
|| String.valueOf(s.getServicePrice()).contains(q)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String safe(String v) {
|
||||||
|
return v == null ? "" : v.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
void btnAddClicked(ActionEvent event) {
|
void btnAddClicked(ActionEvent event) {
|
||||||
@@ -84,6 +132,10 @@ public class ServiceController {
|
|||||||
ServiceDB.deleteService(service.getServiceId());
|
ServiceDB.deleteService(service.getServiceId());
|
||||||
loadServices();
|
loadServices();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ServiceController.btnDeleteClicked",
|
||||||
|
ex,
|
||||||
|
"Deleting service with ID: " + service.getServiceId());
|
||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,6 +163,10 @@ public class ServiceController {
|
|||||||
loadServices();
|
loadServices();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"ServiceController.openDialog",
|
||||||
|
e,
|
||||||
|
"Opening service dialog in " + mode + " mode");
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,112 @@
|
|||||||
|
package org.example.petshopdesktop.controllers;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import javafx.collections.transformation.FilteredList;
|
||||||
|
import javafx.event.ActionEvent;
|
||||||
|
import javafx.fxml.FXML;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TableColumn;
|
||||||
|
import javafx.scene.control.TableView;
|
||||||
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
|
import org.example.petshopdesktop.auth.UserSession;
|
||||||
|
import org.example.petshopdesktop.database.UserDB;
|
||||||
|
import org.example.petshopdesktop.models.StaffAccount;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
|
||||||
|
public class StaffAccountsController {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableView<StaffAccount> tvStaff;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<StaffAccount, String> colUsername;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<StaffAccount, String> colName;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<StaffAccount, String> colEmail;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<StaffAccount, String> colPhone;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<StaffAccount, String> colStatus;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<StaffAccount, java.sql.Timestamp> colCreated;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextField txtSearch;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblError;
|
||||||
|
|
||||||
|
private final ObservableList<StaffAccount> staffAccounts = FXCollections.observableArrayList();
|
||||||
|
private FilteredList<StaffAccount> filtered;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
public void initialize() {
|
||||||
|
colUsername.setCellValueFactory(new PropertyValueFactory<>("username"));
|
||||||
|
colName.setCellValueFactory(new PropertyValueFactory<>("fullName"));
|
||||||
|
colEmail.setCellValueFactory(new PropertyValueFactory<>("email"));
|
||||||
|
colPhone.setCellValueFactory(new PropertyValueFactory<>("phone"));
|
||||||
|
colStatus.setCellValueFactory(new PropertyValueFactory<>("status"));
|
||||||
|
colCreated.setCellValueFactory(new PropertyValueFactory<>("createdAt"));
|
||||||
|
|
||||||
|
filtered = new FilteredList<>(staffAccounts, a -> true);
|
||||||
|
tvStaff.setItems(filtered);
|
||||||
|
|
||||||
|
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
||||||
|
|
||||||
|
if (!UserSession.getInstance().isAdmin()) {
|
||||||
|
lblError.setText("Access restricted.");
|
||||||
|
tvStaff.setDisable(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
void btnRefreshClicked(ActionEvent event) {
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refresh() {
|
||||||
|
lblError.setText("");
|
||||||
|
try {
|
||||||
|
staffAccounts.setAll(UserDB.getStaffAccounts());
|
||||||
|
} catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException("StaffAccountsController.refresh", e, "Loading staff accounts");
|
||||||
|
lblError.setText("Could not load staff accounts.");
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
ActivityLogger.getInstance().logException("StaffAccountsController.refresh", e, "Database connection");
|
||||||
|
lblError.setText("Database is not connected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyFilter(String text) {
|
||||||
|
String q = text == null ? "" : text.trim().toLowerCase();
|
||||||
|
if (q.isEmpty()) {
|
||||||
|
filtered.setPredicate(a -> true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
filtered.setPredicate(a ->
|
||||||
|
safe(a.getUsername()).contains(q)
|
||||||
|
|| safe(a.getFullName()).contains(q)
|
||||||
|
|| safe(a.getEmail()).contains(q)
|
||||||
|
|| safe(a.getPhone()).contains(q)
|
||||||
|
|| safe(a.getStatus()).contains(q)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String safe(String v) {
|
||||||
|
return v == null ? "" : v.toLowerCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@ import javafx.stage.Stage;
|
|||||||
import org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController;
|
import org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController;
|
||||||
import org.example.petshopdesktop.database.SupplierDB;
|
import org.example.petshopdesktop.database.SupplierDB;
|
||||||
import org.example.petshopdesktop.models.Supplier;
|
import org.example.petshopdesktop.models.Supplier;
|
||||||
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -87,6 +88,14 @@ public class SupplierController {
|
|||||||
displayFilteredSupplier(newValue);
|
displayFilteredSupplier(newValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//EventListener for DELETE key
|
||||||
|
tvSuppliers.setOnKeyPressed(event -> {
|
||||||
|
if (event.getCode() == javafx.scene.input.KeyCode.DELETE) {
|
||||||
|
if (tvSuppliers.getSelectionModel().getSelectedItem() != null) {
|
||||||
|
btnDeleteClicked(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,6 +108,10 @@ public class SupplierController {
|
|||||||
try{
|
try{
|
||||||
data = SupplierDB.getSuppliers();
|
data = SupplierDB.getSuppliers();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"SupplierController.displaySupplier",
|
||||||
|
e,
|
||||||
|
"Fetching supplier data for table display");
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +134,10 @@ public class SupplierController {
|
|||||||
tvSuppliers.setItems(data);
|
tvSuppliers.setItems(data);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"SupplierController.displayFilteredSupplier",
|
||||||
|
e,
|
||||||
|
"Filtering suppliers with filter: " + filter);
|
||||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,6 +167,7 @@ public class SupplierController {
|
|||||||
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
||||||
question.setHeaderText("Please confirm delete");
|
question.setHeaderText("Please confirm delete");
|
||||||
question.setContentText("Are you sure you want to delete this supplier?");
|
question.setContentText("Are you sure you want to delete this supplier?");
|
||||||
|
question.getDialogPane().lookupButton(ButtonType.OK).requestFocus();
|
||||||
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
||||||
|
|
||||||
//if confirmed, start deletion
|
//if confirmed, start deletion
|
||||||
@@ -161,6 +179,10 @@ public class SupplierController {
|
|||||||
numRows = SupplierDB.deleteSupplier(supId);
|
numRows = SupplierDB.deleteSupplier(supId);
|
||||||
}
|
}
|
||||||
catch (SQLIntegrityConstraintViolationException e){
|
catch (SQLIntegrityConstraintViolationException e){
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"SupplierController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting supplier (integrity constraint violation) with ID: " + supId);
|
||||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
alert.setHeaderText("Database Operation Error");
|
alert.setHeaderText("Database Operation Error");
|
||||||
alert.setContentText("Delete failed\n" +
|
alert.setContentText("Delete failed\n" +
|
||||||
@@ -169,6 +191,10 @@ public class SupplierController {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"SupplierController.btnDeleteClicked",
|
||||||
|
e,
|
||||||
|
"Deleting supplier with ID: " + supId);
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +248,10 @@ public class SupplierController {
|
|||||||
try{
|
try{
|
||||||
scene = new Scene(fxmlLoader.load());
|
scene = new Scene(fxmlLoader.load());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
ActivityLogger.getInstance().logException(
|
||||||
|
"SupplierController.openDialog",
|
||||||
|
e,
|
||||||
|
"Loading supplier dialog in " + mode + " mode");
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
SupplierDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
SupplierDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
||||||
|
|||||||
Reference in New Issue
Block a user