From ffa45044e464642a7043cf55d6b965c4cde8c76d Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Wed, 25 Feb 2026 09:21:18 -0700 Subject: [PATCH] Add error dialog for view loading failures and fix btnPurchaseOrdersClicked signature --- .../controllers/MainLayoutController.java | 105 +++++++++++------- 1 file changed, 65 insertions(+), 40 deletions(-) diff --git a/src/main/java/org/example/petshopdesktop/controllers/MainLayoutController.java b/src/main/java/org/example/petshopdesktop/controllers/MainLayoutController.java index 8198d517..6f60eb7d 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/MainLayoutController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/MainLayoutController.java @@ -5,16 +5,14 @@ import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; +import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import org.example.petshopdesktop.auth.UserSession; +import org.example.petshopdesktop.util.ActivityLogger; -/* -Petshop Desktop -Purpose: Main application shell controller, includes navigation and UI level role based access control. -*/ public class MainLayoutController { @FXML @@ -50,6 +48,9 @@ public class MainLayoutController { @FXML private Button btnSuppliers; + @FXML + private Button btnStaffAccounts; + @FXML private Label lblUsername; @@ -102,11 +103,17 @@ public class MainLayoutController { } @FXML - void btnPurchaseOrdersClicked() { + void btnPurchaseOrdersClicked(ActionEvent event) { loadView("purchase-order-view.fxml"); updateButtons(btnPurchaseOrders); } + @FXML + void btnStaffAccountsClicked(ActionEvent event) { + loadView("staff-accounts-view.fxml"); + updateButtons(btnStaffAccounts); + } + @FXML void btnServicesClicked(ActionEvent event) { loadView("service-view.fxml"); @@ -117,14 +124,10 @@ public class MainLayoutController { void btnSuppliersClicked(ActionEvent event) { loadView("supplier-view.fxml"); updateButtons(btnSuppliers); - } - - @FXML void btnLogoutClicked(ActionEvent event) { - // Logout clears session state before returning to the login view. UserSession.getInstance().logout(); try { FXMLLoader loader = new FXMLLoader( @@ -134,6 +137,10 @@ public class MainLayoutController { stage.setScene(scene); stage.setTitle("Pet Shop Manager - Login"); } catch (Exception e) { + ActivityLogger.getInstance().logException( + "MainLayoutController.btnLogoutClicked", + e, + "Loading login view after logout"); System.err.println("Error loading login view: " + e.getMessage()); e.printStackTrace(); } @@ -141,22 +148,22 @@ public class MainLayoutController { @FXML public void initialize() { - // RBAC state is applied once during initial layout load. applyRBAC(); - // Default landing view after successful authentication. loadView("pet-view.fxml"); + updateButtons(btnPets); } private void applyRBAC() { UserSession session = UserSession.getInstance(); - // Session identity is displayed in the header for clarity and auditing. - lblUsername.setText(session.getUsername()); - lblRole.setText(session.getRole().toString()); + String displayName = session.getEmployeeName(); + if (displayName == null || displayName.isBlank()) { + displayName = session.getUsername(); + } + lblUsername.setText(displayName == null ? "" : displayName); + lblRole.setText("Leon's Petstore"); - // UI level RBAC hides admin only navigation entries for non admin users. - // setManaged(false) removes the node from layout calculations to avoid empty spacing. boolean isAdmin = session.isAdmin(); btnInventory.setVisible(isAdmin); btnInventory.setManaged(isAdmin); @@ -165,47 +172,65 @@ public class MainLayoutController { btnProductSuppliers.setVisible(isAdmin); btnProductSuppliers.setManaged(isAdmin); - // Privileged operations should still be enforced within the relevant controllers and database methods. + btnPurchaseOrders.setVisible(isAdmin); + btnPurchaseOrders.setManaged(isAdmin); + + btnStaffAccounts.setVisible(isAdmin); + btnStaffAccounts.setManaged(isAdmin); + + btnSalesHistory.setText(isAdmin ? "Sales History" : "Sales"); + } - /** - * Load a view when a button is clicked on the navigation - * @param fxmlFile the fxmlFile name to be loaded - */ private void loadView(String fxmlFile) { try { - //Get the location of the fxml for view FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/modelviews/" + fxmlFile)); Parent view = loader.load(); - //Clear any content that is in the stack pane and add the new view to display spContentArea.getChildren().clear(); spContentArea.getChildren().add(view); } catch (Exception e) { + ActivityLogger.getInstance().logException( + "MainLayoutController.loadView", + e, + "Loading view: " + fxmlFile); System.err.println("Error loading view: " + fxmlFile); e.printStackTrace(); + + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle("View Load Error"); + alert.setHeaderText("Failed to load: " + fxmlFile); + alert.setContentText("Error: " + e.getMessage() + "\n\nCheck console for details."); + alert.showAndWait(); } } - /** - * update the button visuals when a button is clicked on the navigation - * @param activeButton the button to be set active - */ private void updateButtons(Button activeButton) { - //reset all buttons - Button[] BUTTONS = {btnAdoptions, btnPets, btnAppointments, btnInventory, - btnSalesHistory, btnServices, btnSuppliers, btnProductSuppliers, btnProducts}; - for (Button button : BUTTONS) { - //set all buttons to inactive - button.setStyle("-fx-background-color: transparent; " + - "-fx-text-fill: #CCCCCC; " + - "-fx-cursor: hand"); + String base = "-fx-background-color: transparent; -fx-text-fill: #D5DDE6; -fx-cursor: hand; -fx-background-radius: 10; -fx-alignment: CENTER_LEFT;"; + String active = "-fx-background-color: #FF6B6B; -fx-text-fill: white; -fx-cursor: hand; -fx-background-radius: 10; -fx-alignment: CENTER_LEFT;"; + + Button[] buttons = { + btnAdoptions, + btnPets, + btnAppointments, + btnInventory, + btnSalesHistory, + btnServices, + btnSuppliers, + btnProductSuppliers, + btnProducts, + btnPurchaseOrders, + btnStaffAccounts + }; + + for (Button button : buttons) { + if (button != null) { + button.setStyle(base); + } } - //set active button - activeButton.setStyle("-fx-background-color: #FF6B6B; " + - "-fx-text-fill: white; " + - "-fx-cursor: hand; " + - "-fx-background-radius: 8"); + if (activeButton != null) { + activeButton.setStyle(active); + } } }