made it so staff cannot change the status of pets for desktop for adopted or owned
This commit is contained in:
@@ -164,6 +164,10 @@ public class PetDetailFragment extends Fragment {
|
|||||||
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
||||||
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
||||||
}
|
}
|
||||||
|
if ("Pending".equalsIgnoreCase(status)) {
|
||||||
|
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
||||||
|
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
||||||
|
}
|
||||||
|
|
||||||
PetDTO petDTO = new PetDTO();
|
PetDTO petDTO = new PetDTO();
|
||||||
petDTO.setPetName(name);
|
petDTO.setPetName(name);
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ public class PetProfileFragment extends Fragment {
|
|||||||
|
|
||||||
String status = pet.getPetStatus();
|
String status = pet.getPetStatus();
|
||||||
|
|
||||||
if ("Adopted".equalsIgnoreCase(status) || "Owned".equalsIgnoreCase(status)) {
|
if ("Adopted".equalsIgnoreCase(status) || "Owned".equalsIgnoreCase(status) || "Pending".equalsIgnoreCase(status)) {
|
||||||
binding.layoutPetOwner.setVisibility(View.VISIBLE);
|
binding.layoutPetOwner.setVisibility(View.VISIBLE);
|
||||||
if (pet.getCustomerName() != null && !pet.getCustomerName().isEmpty()) {
|
if (pet.getCustomerName() != null && !pet.getCustomerName().isEmpty()) {
|
||||||
binding.tvPetOwner.setText(pet.getCustomerName());
|
binding.tvPetOwner.setText(pet.getCustomerName());
|
||||||
@@ -137,7 +137,7 @@ public class PetProfileFragment extends Fragment {
|
|||||||
binding.layoutPetOwner.setVisibility(View.GONE);
|
binding.layoutPetOwner.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("Available".equalsIgnoreCase(status) || "Adopted".equalsIgnoreCase(status)) {
|
if ("Available".equalsIgnoreCase(status) || "Adopted".equalsIgnoreCase(status) || "Pending".equalsIgnoreCase(status)) {
|
||||||
binding.layoutPetStore.setVisibility(View.VISIBLE);
|
binding.layoutPetStore.setVisibility(View.VISIBLE);
|
||||||
if (pet.getStoreName() != null && !pet.getStoreName().isEmpty()) {
|
if (pet.getStoreName() != null && !pet.getStoreName().isEmpty()) {
|
||||||
binding.tvPetStore.setText(pet.getStoreName());
|
binding.tvPetStore.setText(pet.getStoreName());
|
||||||
|
|||||||
@@ -271,6 +271,7 @@ public class AdoptionService {
|
|||||||
pet.setStore(null);
|
pet.setStore(null);
|
||||||
} else if (ADOPTION_STATUS_PENDING.equalsIgnoreCase(adoptionStatus)) {
|
} else if (ADOPTION_STATUS_PENDING.equalsIgnoreCase(adoptionStatus)) {
|
||||||
pet.setPetStatus(PET_STATUS_PENDING);
|
pet.setPetStatus(PET_STATUS_PENDING);
|
||||||
|
pet.setOwner(customer);
|
||||||
} else {
|
} else {
|
||||||
pet.setPetStatus(PET_STATUS_AVAILABLE);
|
pet.setPetStatus(PET_STATUS_AVAILABLE);
|
||||||
pet.setOwner(null);
|
pet.setOwner(null);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ public class UserResponse {
|
|||||||
private String phone;
|
private String phone;
|
||||||
private String role;
|
private String role;
|
||||||
private Boolean active;
|
private Boolean active;
|
||||||
|
private Integer loyaltyPoints;
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
private LocalDateTime updatedAt;
|
private LocalDateTime updatedAt;
|
||||||
|
|
||||||
@@ -72,6 +73,14 @@ public class UserResponse {
|
|||||||
this.active = active;
|
this.active = active;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer getLoyaltyPoints() {
|
||||||
|
return loyaltyPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoyaltyPoints(Integer loyaltyPoints) {
|
||||||
|
this.loyaltyPoints = loyaltyPoints;
|
||||||
|
}
|
||||||
|
|
||||||
public LocalDateTime getCreatedAt() {
|
public LocalDateTime getCreatedAt() {
|
||||||
return createdAt;
|
return createdAt;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,21 +13,55 @@ import javafx.scene.control.Label;
|
|||||||
import javafx.scene.control.TableColumn;
|
import javafx.scene.control.TableColumn;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.TableView;
|
||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.stage.Modality;
|
import javafx.stage.Modality;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
import org.example.petshopdesktop.api.dto.user.UserResponse;
|
import org.example.petshopdesktop.api.dto.user.UserResponse;
|
||||||
import org.example.petshopdesktop.api.endpoints.UserApi;
|
|
||||||
import org.example.petshopdesktop.api.endpoints.CustomerApi;
|
import org.example.petshopdesktop.api.endpoints.CustomerApi;
|
||||||
|
import org.example.petshopdesktop.api.endpoints.UserApi;
|
||||||
import org.example.petshopdesktop.auth.UserSession;
|
import org.example.petshopdesktop.auth.UserSession;
|
||||||
import org.example.petshopdesktop.util.ActivityLogger;
|
import org.example.petshopdesktop.util.ActivityLogger;
|
||||||
import org.example.petshopdesktop.util.TableViewSupport;
|
import org.example.petshopdesktop.util.TableViewSupport;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class StaffAccountsController {
|
public class StaffAccountsController {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private VBox staffSection;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableView<UserResponse> tvCustomers;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<UserResponse, String> colCustomerUsername;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<UserResponse, String> colCustomerName;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<UserResponse, String> colCustomerEmail;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<UserResponse, String> colCustomerPhone;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<UserResponse, Object> colCustomerLoyaltyPoints;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<UserResponse, String> colCustomerStatus;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TableColumn<UserResponse, Object> colCustomerCreated;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextField txtSearchCustomer;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Button btnEditCustomer;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TableView<UserResponse> tvStaff;
|
private TableView<UserResponse> tvStaff;
|
||||||
|
|
||||||
@@ -55,12 +89,6 @@ public class StaffAccountsController {
|
|||||||
@FXML
|
@FXML
|
||||||
private TextField txtSearch;
|
private TextField txtSearch;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Label lblError;
|
|
||||||
|
|
||||||
@FXML
|
|
||||||
private Label lblStatus;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private Button btnRefresh;
|
private Button btnRefresh;
|
||||||
|
|
||||||
@@ -70,11 +98,38 @@ public class StaffAccountsController {
|
|||||||
@FXML
|
@FXML
|
||||||
private Button btnEditAccount;
|
private Button btnEditAccount;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblError;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblStatus;
|
||||||
|
|
||||||
|
private final ObservableList<UserResponse> customerAccounts = FXCollections.observableArrayList();
|
||||||
|
private FilteredList<UserResponse> filteredCustomers;
|
||||||
|
|
||||||
private final ObservableList<UserResponse> staffAccounts = FXCollections.observableArrayList();
|
private final ObservableList<UserResponse> staffAccounts = FXCollections.observableArrayList();
|
||||||
private FilteredList<UserResponse> filtered;
|
private FilteredList<UserResponse> filteredStaff;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
|
colCustomerUsername.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getUsername()));
|
||||||
|
colCustomerName.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getFullName()));
|
||||||
|
colCustomerEmail.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getEmail()));
|
||||||
|
colCustomerPhone.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getPhone()));
|
||||||
|
colCustomerLoyaltyPoints.setCellValueFactory(data -> new javafx.beans.property.SimpleObjectProperty<>(data.getValue().getLoyaltyPoints()));
|
||||||
|
colCustomerStatus.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getActive() != null && data.getValue().getActive() ? "Active" : "Inactive"));
|
||||||
|
colCustomerCreated.setCellValueFactory(data -> new javafx.beans.property.SimpleObjectProperty<>(data.getValue().getCreatedAt()));
|
||||||
|
|
||||||
|
filteredCustomers = new FilteredList<>(customerAccounts, a -> true);
|
||||||
|
TableViewSupport.bindSortedItems(tvCustomers, filteredCustomers);
|
||||||
|
TableViewSupport.installDoubleClickAction(tvCustomers, this::openEditDialog);
|
||||||
|
|
||||||
|
tvCustomers.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) ->
|
||||||
|
btnEditCustomer.setDisable(newVal == null));
|
||||||
|
btnEditCustomer.setDisable(true);
|
||||||
|
|
||||||
|
txtSearchCustomer.textProperty().addListener((obs, o, n) -> applyCustomerFilter(n));
|
||||||
|
|
||||||
colUsername.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getUsername()));
|
colUsername.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getUsername()));
|
||||||
colName.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getFullName()));
|
colName.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getFullName()));
|
||||||
colEmail.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getEmail()));
|
colEmail.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getEmail()));
|
||||||
@@ -83,33 +138,39 @@ public class StaffAccountsController {
|
|||||||
colStatus.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getActive() != null && data.getValue().getActive() ? "Active" : "Inactive"));
|
colStatus.setCellValueFactory(data -> new javafx.beans.property.SimpleStringProperty(data.getValue().getActive() != null && data.getValue().getActive() ? "Active" : "Inactive"));
|
||||||
colCreated.setCellValueFactory(data -> new javafx.beans.property.SimpleObjectProperty<>(data.getValue().getCreatedAt()));
|
colCreated.setCellValueFactory(data -> new javafx.beans.property.SimpleObjectProperty<>(data.getValue().getCreatedAt()));
|
||||||
|
|
||||||
filtered = new FilteredList<>(staffAccounts, a -> true);
|
filteredStaff = new FilteredList<>(staffAccounts, a -> true);
|
||||||
TableViewSupport.bindSortedItems(tvStaff, filtered);
|
TableViewSupport.bindSortedItems(tvStaff, filteredStaff);
|
||||||
TableViewSupport.installDoubleClickAction(tvStaff, this::openEditDialog);
|
TableViewSupport.installDoubleClickAction(tvStaff, this::openEditDialog);
|
||||||
|
|
||||||
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
tvStaff.getSelectionModel().selectedItemProperty().addListener((obs, oldVal, newVal) ->
|
||||||
|
btnEditAccount.setDisable(newVal == null));
|
||||||
tvStaff.getSelectionModel().selectedItemProperty().addListener((obs, oldValue, newValue) -> {
|
|
||||||
if (btnEditAccount != null) {
|
|
||||||
btnEditAccount.setDisable(newValue == null);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (btnEditAccount != null) {
|
|
||||||
btnEditAccount.setDisable(true);
|
btnEditAccount.setDisable(true);
|
||||||
}
|
|
||||||
|
txtSearch.textProperty().addListener((obs, o, n) -> applyStaffFilter(n));
|
||||||
|
|
||||||
|
boolean isAdmin = UserSession.getInstance().isAdmin();
|
||||||
|
staffSection.setVisible(isAdmin);
|
||||||
|
staffSection.setManaged(isAdmin);
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
void btnRefreshClicked(ActionEvent event) {
|
void btnRefreshClicked(ActionEvent event) {
|
||||||
|
txtSearchCustomer.clear();
|
||||||
txtSearch.clear();
|
txtSearch.clear();
|
||||||
|
TableViewSupport.clearSort(tvCustomers);
|
||||||
TableViewSupport.clearSort(tvStaff);
|
TableViewSupport.clearSort(tvStaff);
|
||||||
refresh();
|
refresh();
|
||||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
void btnEditCustomerClicked(ActionEvent event) {
|
||||||
|
lblError.setText("");
|
||||||
|
openEditDialog(tvCustomers.getSelectionModel().getSelectedItem());
|
||||||
|
}
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
void btnCreateAccountClicked(ActionEvent event) {
|
void btnCreateAccountClicked(ActionEvent event) {
|
||||||
lblError.setText("");
|
lblError.setText("");
|
||||||
@@ -132,8 +193,7 @@ public class StaffAccountsController {
|
|||||||
@FXML
|
@FXML
|
||||||
void btnEditAccountClicked(ActionEvent event) {
|
void btnEditAccountClicked(ActionEvent event) {
|
||||||
lblError.setText("");
|
lblError.setText("");
|
||||||
UserResponse selected = tvStaff.getSelectionModel().getSelectedItem();
|
openEditDialog(tvStaff.getSelectionModel().getSelectedItem());
|
||||||
openEditDialog(selected);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openEditDialog(UserResponse selected) {
|
private void openEditDialog(UserResponse selected) {
|
||||||
@@ -154,7 +214,8 @@ public class StaffAccountsController {
|
|||||||
try {
|
try {
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/staff-edit-dialog-view.fxml"));
|
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/staff-edit-dialog-view.fxml"));
|
||||||
Stage dialog = new Stage();
|
Stage dialog = new Stage();
|
||||||
dialog.initOwner(tvStaff.getScene().getWindow());
|
Stage owner = (tvStaff.getScene() != null) ? (Stage) tvStaff.getScene().getWindow() : (Stage) tvCustomers.getScene().getWindow();
|
||||||
|
dialog.initOwner(owner);
|
||||||
dialog.initModality(Modality.APPLICATION_MODAL);
|
dialog.initModality(Modality.APPLICATION_MODAL);
|
||||||
dialog.setTitle("Edit User Account");
|
dialog.setTitle("Edit User Account");
|
||||||
dialog.setScene(new Scene(loader.load()));
|
dialog.setScene(new Scene(loader.load()));
|
||||||
@@ -164,31 +225,45 @@ public class StaffAccountsController {
|
|||||||
dialog.showAndWait();
|
dialog.showAndWait();
|
||||||
refresh();
|
refresh();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
ActivityLogger.getInstance().logException("StaffAccountsController.btnEditAccountClicked", e, "Opening user edit dialog");
|
ActivityLogger.getInstance().logException("StaffAccountsController.openEditDialog", e, "Opening user edit dialog");
|
||||||
lblError.setText("Could not open user account editor.");
|
lblError.setText("Could not open user account editor.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refresh() {
|
private void refresh() {
|
||||||
lblError.setText("");
|
lblError.setText("");
|
||||||
|
tvCustomers.setDisable(true);
|
||||||
tvStaff.setDisable(true);
|
tvStaff.setDisable(true);
|
||||||
|
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
UserSession session = UserSession.getInstance();
|
Comparator<UserResponse> byCreated = Comparator.comparing(
|
||||||
List<UserResponse> users;
|
UserResponse::getCreatedAt, Comparator.nullsLast(Comparator.reverseOrder()));
|
||||||
if (session.isAdmin()) {
|
|
||||||
users = UserApi.getInstance().listUsers(null);
|
final List<UserResponse> customers;
|
||||||
|
final List<UserResponse> staff;
|
||||||
|
|
||||||
|
if (UserSession.getInstance().isAdmin()) {
|
||||||
|
List<UserResponse> allUsers = UserApi.getInstance().listUsers(null);
|
||||||
|
customers = allUsers.stream()
|
||||||
|
.filter(u -> "CUSTOMER".equalsIgnoreCase(u.getRole()))
|
||||||
|
.sorted(byCreated)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
staff = allUsers.stream()
|
||||||
|
.filter(u -> !"CUSTOMER".equalsIgnoreCase(u.getRole()))
|
||||||
|
.sorted(byCreated)
|
||||||
|
.collect(Collectors.toList());
|
||||||
} else {
|
} else {
|
||||||
users = CustomerApi.getInstance().listCustomers(null);
|
customers = CustomerApi.getInstance().listCustomers(null).stream()
|
||||||
|
.sorted(byCreated)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
staff = List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<UserResponse> sortedUsers = users.stream()
|
|
||||||
.sorted(Comparator.comparing(UserResponse::getCreatedAt, Comparator.nullsLast(Comparator.reverseOrder())))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
|
|
||||||
Platform.runLater(() -> {
|
Platform.runLater(() -> {
|
||||||
staffAccounts.setAll(sortedUsers);
|
customerAccounts.setAll(customers);
|
||||||
|
staffAccounts.setAll(staff);
|
||||||
|
tvCustomers.setDisable(false);
|
||||||
tvStaff.setDisable(false);
|
tvStaff.setDisable(false);
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -198,20 +273,34 @@ public class StaffAccountsController {
|
|||||||
lblError.setText(message == null || message.isBlank()
|
lblError.setText(message == null || message.isBlank()
|
||||||
? "Could not load user accounts."
|
? "Could not load user accounts."
|
||||||
: "Could not load user accounts: " + message);
|
: "Could not load user accounts: " + message);
|
||||||
|
tvCustomers.setDisable(false);
|
||||||
tvStaff.setDisable(false);
|
tvStaff.setDisable(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyFilter(String text) {
|
private void applyCustomerFilter(String text) {
|
||||||
String q = text == null ? "" : text.trim().toLowerCase();
|
String q = text == null ? "" : text.trim().toLowerCase();
|
||||||
if (q.isEmpty()) {
|
if (q.isEmpty()) {
|
||||||
filtered.setPredicate(a -> true);
|
filteredCustomers.setPredicate(a -> true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
filteredCustomers.setPredicate(a ->
|
||||||
|
safe(a.getUsername()).contains(q)
|
||||||
|
|| safe(a.getFullName()).contains(q)
|
||||||
|
|| safe(a.getEmail()).contains(q)
|
||||||
|
|| safe(a.getPhone()).contains(q)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
filtered.setPredicate(a ->
|
private void applyStaffFilter(String text) {
|
||||||
|
String q = text == null ? "" : text.trim().toLowerCase();
|
||||||
|
if (q.isEmpty()) {
|
||||||
|
filteredStaff.setPredicate(a -> true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filteredStaff.setPredicate(a ->
|
||||||
safe(a.getUsername()).contains(q)
|
safe(a.getUsername()).contains(q)
|
||||||
|| safe(a.getFullName()).contains(q)
|
|| safe(a.getFullName()).contains(q)
|
||||||
|| safe(a.getEmail()).contains(q)
|
|| safe(a.getEmail()).contains(q)
|
||||||
|
|||||||
@@ -132,9 +132,7 @@ public class PetDialogController {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setFieldVisibility(vbCustomerField, false);
|
updateStatusFieldVisibility(null);
|
||||||
setFieldVisibility(vbStoreField, false);
|
|
||||||
setFieldVisibility(vbPriceField, true);
|
|
||||||
|
|
||||||
loadSpecies();
|
loadSpecies();
|
||||||
|
|
||||||
@@ -174,18 +172,18 @@ public class PetDialogController {
|
|||||||
String speciesValue = cbPetSpecies.getValue() != null ? cbPetSpecies.getValue().trim() : "";
|
String speciesValue = cbPetSpecies.getValue() != null ? cbPetSpecies.getValue().trim() : "";
|
||||||
if (speciesValue.isEmpty()) errorMsg += "Species is required\n";
|
if (speciesValue.isEmpty()) errorMsg += "Species is required\n";
|
||||||
String selectedStatus = cbPetStatus.getValue();
|
String selectedStatus = cbPetStatus.getValue();
|
||||||
boolean needsPrice = !("Owned".equalsIgnoreCase(selectedStatus) || "Adopted".equalsIgnoreCase(selectedStatus));
|
|
||||||
if (needsPrice) {
|
|
||||||
errorMsg += Validator.isPresent(txtPetPrice.getText(), "Price");
|
errorMsg += Validator.isPresent(txtPetPrice.getText(), "Price");
|
||||||
}
|
|
||||||
if (cbPetStatus.getSelectionModel().getSelectedItem() == null){
|
if (cbPetStatus.getSelectionModel().getSelectedItem() == null){
|
||||||
errorMsg += "Status is required";
|
errorMsg += "Status is required";
|
||||||
}
|
}
|
||||||
if ("Owned".equalsIgnoreCase(selectedStatus) && cbCustomer.getValue() == null && UserSession.getInstance().isAdmin()) {
|
boolean needsCustomer = "Owned".equalsIgnoreCase(selectedStatus)
|
||||||
errorMsg += "Customer is required for Owned status\n";
|
|| "Adopted".equalsIgnoreCase(selectedStatus)
|
||||||
|
|| "Pending".equalsIgnoreCase(selectedStatus);
|
||||||
|
boolean needsStore = requiresStore(selectedStatus);
|
||||||
|
if (needsCustomer && cbCustomer.getValue() == null && UserSession.getInstance().isAdmin()) {
|
||||||
|
errorMsg += "Customer is required for " + selectedStatus + " status\n";
|
||||||
}
|
}
|
||||||
boolean storeRequired = requiresStore(selectedStatus) && !"Adopted".equalsIgnoreCase(selectedStatus);
|
if (needsStore && cbStore.getValue() == null) {
|
||||||
if (storeRequired && cbStore.getValue() == null) {
|
|
||||||
errorMsg += "Store is required for " + selectedStatus + " status\n";
|
errorMsg += "Store is required for " + selectedStatus + " status\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,15 +191,11 @@ public class PetDialogController {
|
|||||||
errorMsg += Validator.isLessThanVarChars(txtPetName.getText(), "Pet Name", 50);
|
errorMsg += Validator.isLessThanVarChars(txtPetName.getText(), "Pet Name", 50);
|
||||||
errorMsg += Validator.isLessThanVarChars(speciesValue, "Species", 50);
|
errorMsg += Validator.isLessThanVarChars(speciesValue, "Species", 50);
|
||||||
errorMsg += Validator.isLessThanVarChars(txtPetBreed.getText(), "Breed", 50);
|
errorMsg += Validator.isLessThanVarChars(txtPetBreed.getText(), "Breed", 50);
|
||||||
if (needsPrice) {
|
|
||||||
errorMsg += Validator.isLessThanVarChars(txtPetPrice.getText(), "Price", 12);
|
errorMsg += Validator.isLessThanVarChars(txtPetPrice.getText(), "Price", 12);
|
||||||
}
|
|
||||||
errorMsg += Validator.isLessThanVarChars(txtPetAge.getText(), "Age", 11);
|
errorMsg += Validator.isLessThanVarChars(txtPetAge.getText(), "Age", 11);
|
||||||
|
|
||||||
//Check validation (format)
|
//Check validation (format)
|
||||||
if (needsPrice) {
|
|
||||||
errorMsg += Validator.isNonNegativeDouble(txtPetPrice.getText(), "Price");
|
errorMsg += Validator.isNonNegativeDouble(txtPetPrice.getText(), "Price");
|
||||||
}
|
|
||||||
errorMsg += Validator.isPositiveInteger(txtPetAge.getText(), "Age");
|
errorMsg += Validator.isPositiveInteger(txtPetAge.getText(), "Age");
|
||||||
|
|
||||||
if(errorMsg.isEmpty()){
|
if(errorMsg.isEmpty()){
|
||||||
@@ -263,9 +257,7 @@ public class PetDialogController {
|
|||||||
request.setPetSpecies(cbPetSpecies.getValue() != null ? cbPetSpecies.getValue().trim() : "");
|
request.setPetSpecies(cbPetSpecies.getValue() != null ? cbPetSpecies.getValue().trim() : "");
|
||||||
request.setPetBreed(txtPetBreed.getText());
|
request.setPetBreed(txtPetBreed.getText());
|
||||||
request.setPetStatus(cbPetStatus.getValue());
|
request.setPetStatus(cbPetStatus.getValue());
|
||||||
String buildStatus = cbPetStatus.getValue();
|
if (txtPetPrice.getText() != null && !txtPetPrice.getText().isBlank()) {
|
||||||
boolean buildNeedsPrice = !("Owned".equalsIgnoreCase(buildStatus) || "Adopted".equalsIgnoreCase(buildStatus));
|
|
||||||
if (buildNeedsPrice && txtPetPrice.getText() != null && !txtPetPrice.getText().isBlank()) {
|
|
||||||
try {
|
try {
|
||||||
request.setPetPrice(new BigDecimal(txtPetPrice.getText()));
|
request.setPetPrice(new BigDecimal(txtPetPrice.getText()));
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
@@ -282,7 +274,10 @@ public class PetDialogController {
|
|||||||
request.setPetAge(age);
|
request.setPetAge(age);
|
||||||
|
|
||||||
String status = cbPetStatus.getValue();
|
String status = cbPetStatus.getValue();
|
||||||
if (("Owned".equalsIgnoreCase(status) || "Adopted".equalsIgnoreCase(status)) && cbCustomer.getValue() != null) {
|
boolean customerApplicable = "Owned".equalsIgnoreCase(status)
|
||||||
|
|| "Adopted".equalsIgnoreCase(status)
|
||||||
|
|| "Pending".equalsIgnoreCase(status);
|
||||||
|
if (customerApplicable && cbCustomer.getValue() != null) {
|
||||||
request.setCustomerId(cbCustomer.getValue().getId());
|
request.setCustomerId(cbCustomer.getValue().getId());
|
||||||
}
|
}
|
||||||
if (requiresStore(status) && cbStore.getValue() != null) {
|
if (requiresStore(status) && cbStore.getValue() != null) {
|
||||||
@@ -407,9 +402,17 @@ public class PetDialogController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateStatusFieldVisibility(cbPetStatus.getValue());
|
updateStatusFieldVisibility(cbPetStatus.getValue());
|
||||||
|
applyStatusLock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyStatusLock() {
|
||||||
|
String status = cbPetStatus.getValue();
|
||||||
|
boolean isRestricted = "Adopted".equalsIgnoreCase(status) || "Owned".equalsIgnoreCase(status);
|
||||||
|
boolean isStaff = !UserSession.getInstance().isAdmin();
|
||||||
|
cbPetStatus.setDisable(isRestricted && isStaff);
|
||||||
|
}
|
||||||
|
|
||||||
public void setMode(String mode) {
|
public void setMode(String mode) {
|
||||||
this.mode = mode;
|
this.mode = mode;
|
||||||
lblMode.setText(mode + " Pet");
|
lblMode.setText(mode + " Pet");
|
||||||
@@ -489,28 +492,27 @@ public class PetDialogController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void updateStatusFieldVisibility(String status) {
|
private void updateStatusFieldVisibility(String status) {
|
||||||
boolean statusNeedsCustomer = "Owned".equalsIgnoreCase(status) || "Adopted".equalsIgnoreCase(status);
|
if (status == null) {
|
||||||
boolean needsCustomer = statusNeedsCustomer && UserSession.getInstance().isAdmin();
|
vbPriceField.setDisable(false);
|
||||||
boolean storeBased = requiresStore(status);
|
vbCustomerField.setDisable(true);
|
||||||
boolean needsPrice = !statusNeedsCustomer;
|
vbStoreField.setDisable(false);
|
||||||
setFieldVisibility(vbCustomerField, needsCustomer);
|
return;
|
||||||
setFieldVisibility(vbStoreField, storeBased);
|
}
|
||||||
setFieldVisibility(vbPriceField, needsPrice);
|
boolean isAdmin = UserSession.getInstance().isAdmin();
|
||||||
|
boolean customerApplicable = "Owned".equalsIgnoreCase(status)
|
||||||
|
|| "Adopted".equalsIgnoreCase(status)
|
||||||
|
|| "Pending".equalsIgnoreCase(status);
|
||||||
|
boolean isOwned = "Owned".equalsIgnoreCase(status);
|
||||||
|
|
||||||
|
vbPriceField.setDisable(false);
|
||||||
|
vbCustomerField.setDisable(!customerApplicable || !isAdmin);
|
||||||
|
vbStoreField.setDisable(isOwned);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean requiresStore(String status) {
|
private boolean requiresStore(String status) {
|
||||||
return "Available".equalsIgnoreCase(status)
|
return "Available".equalsIgnoreCase(status)
|
||||||
|| "Pending".equalsIgnoreCase(status)
|
|| "Pending".equalsIgnoreCase(status)
|
||||||
|| "Unadopted".equalsIgnoreCase(status)
|
|
||||||
|| "Adopted".equalsIgnoreCase(status);
|
|| "Adopted".equalsIgnoreCase(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFieldVisibility(VBox field, boolean visible) {
|
|
||||||
if (field == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
field.setVisible(visible);
|
|
||||||
field.setManaged(visible);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<?import javafx.scene.layout.VBox?>
|
<?import javafx.scene.layout.VBox?>
|
||||||
<?import javafx.scene.text.Font?>
|
<?import javafx.scene.text.Font?>
|
||||||
|
|
||||||
<VBox spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/25" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.StaffAccountsController">
|
<VBox spacing="16.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/25" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.StaffAccountsController">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
|
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
|
||||||
</padding>
|
</padding>
|
||||||
@@ -25,22 +25,6 @@
|
|||||||
</font>
|
</font>
|
||||||
</Label>
|
</Label>
|
||||||
<Region HBox.hgrow="ALWAYS" />
|
<Region HBox.hgrow="ALWAYS" />
|
||||||
<Button fx:id="btnCreateAccount" mnemonicParsing="false" onAction="#btnCreateAccountClicked" prefHeight="44.0" style="-fx-background-color: #FF6B6B; -fx-cursor: hand; -fx-background-radius: 8;" text="Create Account" textFill="WHITE">
|
|
||||||
<font>
|
|
||||||
<Font name="System Bold" size="14.0" />
|
|
||||||
</font>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="12.0" left="24.0" right="24.0" top="12.0" />
|
|
||||||
</padding>
|
|
||||||
</Button>
|
|
||||||
<Button fx:id="btnEditAccount" mnemonicParsing="false" onAction="#btnEditAccountClicked" prefHeight="44.0" style="-fx-background-color: #F4A261; -fx-cursor: hand; -fx-background-radius: 8;" text="Edit Account" textFill="WHITE">
|
|
||||||
<font>
|
|
||||||
<Font name="System Bold" size="14.0" />
|
|
||||||
</font>
|
|
||||||
<padding>
|
|
||||||
<Insets bottom="12.0" left="24.0" right="24.0" top="12.0" />
|
|
||||||
</padding>
|
|
||||||
</Button>
|
|
||||||
<Button fx:id="btnRefresh" mnemonicParsing="false" onAction="#btnRefreshClicked" prefHeight="44.0" prefWidth="118.0" style="-fx-background-color: #4ECDC4; -fx-cursor: hand; -fx-background-radius: 8;" text="Refresh" textFill="WHITE">
|
<Button fx:id="btnRefresh" mnemonicParsing="false" onAction="#btnRefreshClicked" prefHeight="44.0" prefWidth="118.0" style="-fx-background-color: #4ECDC4; -fx-cursor: hand; -fx-background-radius: 8;" text="Refresh" textFill="WHITE">
|
||||||
<font>
|
<font>
|
||||||
<Font name="System Bold" size="14.0" />
|
<Font name="System Bold" size="14.0" />
|
||||||
@@ -52,12 +36,91 @@
|
|||||||
</children>
|
</children>
|
||||||
</HBox>
|
</HBox>
|
||||||
|
|
||||||
|
<!-- Customers Section -->
|
||||||
|
<VBox spacing="10.0" VBox.vgrow="ALWAYS">
|
||||||
|
<children>
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="12.0">
|
||||||
|
<children>
|
||||||
|
<Label text="Customers" textFill="#2c3e50">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="20.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Region HBox.hgrow="ALWAYS" />
|
||||||
|
<Button fx:id="btnEditCustomer" mnemonicParsing="false" onAction="#btnEditCustomerClicked" prefHeight="40.0" style="-fx-background-color: #F4A261; -fx-cursor: hand; -fx-background-radius: 8;" text="Edit Customer" textFill="WHITE">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="14.0" />
|
||||||
|
</font>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="10.0" left="20.0" right="20.0" top="10.0" />
|
||||||
|
</padding>
|
||||||
|
</Button>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
|
||||||
<HBox alignment="CENTER_LEFT" spacing="10.0" style="-fx-background-color: white; -fx-background-radius: 14; -fx-border-width: 1; -fx-border-radius: 14; -fx-border-color: #e6e6e6;">
|
<HBox alignment="CENTER_LEFT" spacing="10.0" style="-fx-background-color: white; -fx-background-radius: 14; -fx-border-width: 1; -fx-border-radius: 14; -fx-border-color: #e6e6e6;">
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="10.0" left="15.0" right="15.0" top="10.0" />
|
<Insets bottom="10.0" left="15.0" right="15.0" top="10.0" />
|
||||||
</padding>
|
</padding>
|
||||||
<children>
|
<children>
|
||||||
<TextField fx:id="txtSearch" promptText="Search users..." style="-fx-border-width: 0; -fx-background-color: transparent;" HBox.hgrow="ALWAYS">
|
<TextField fx:id="txtSearchCustomer" promptText="Search customers..." style="-fx-border-width: 0; -fx-background-color: transparent;" HBox.hgrow="ALWAYS">
|
||||||
|
<font>
|
||||||
|
<Font size="15.0" />
|
||||||
|
</font>
|
||||||
|
</TextField>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
|
||||||
|
<TableView fx:id="tvCustomers" style="-fx-background-color: white; -fx-background-radius: 12;" VBox.vgrow="ALWAYS">
|
||||||
|
<columns>
|
||||||
|
<TableColumn fx:id="colCustomerUsername" prefWidth="130.0" text="Username" />
|
||||||
|
<TableColumn fx:id="colCustomerName" prefWidth="160.0" text="Name" />
|
||||||
|
<TableColumn fx:id="colCustomerEmail" prefWidth="200.0" text="Email" />
|
||||||
|
<TableColumn fx:id="colCustomerPhone" prefWidth="130.0" text="Phone" />
|
||||||
|
<TableColumn fx:id="colCustomerLoyaltyPoints" prefWidth="120.0" text="Loyalty Points" />
|
||||||
|
<TableColumn fx:id="colCustomerStatus" prefWidth="90.0" text="Status" />
|
||||||
|
<TableColumn fx:id="colCustomerCreated" prefWidth="150.0" text="Created" />
|
||||||
|
</columns>
|
||||||
|
</TableView>
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
|
|
||||||
|
<!-- Staff Section (admin only) -->
|
||||||
|
<VBox fx:id="staffSection" spacing="10.0" managed="false" visible="false" VBox.vgrow="ALWAYS">
|
||||||
|
<children>
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="12.0">
|
||||||
|
<children>
|
||||||
|
<Label text="Staff" textFill="#2c3e50">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="20.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Region HBox.hgrow="ALWAYS" />
|
||||||
|
<Button fx:id="btnCreateAccount" mnemonicParsing="false" onAction="#btnCreateAccountClicked" prefHeight="40.0" style="-fx-background-color: #FF6B6B; -fx-cursor: hand; -fx-background-radius: 8;" text="Create Account" textFill="WHITE">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="14.0" />
|
||||||
|
</font>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="10.0" left="20.0" right="20.0" top="10.0" />
|
||||||
|
</padding>
|
||||||
|
</Button>
|
||||||
|
<Button fx:id="btnEditAccount" mnemonicParsing="false" onAction="#btnEditAccountClicked" prefHeight="40.0" style="-fx-background-color: #F4A261; -fx-cursor: hand; -fx-background-radius: 8;" text="Edit Account" textFill="WHITE">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="14.0" />
|
||||||
|
</font>
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="10.0" left="20.0" right="20.0" top="10.0" />
|
||||||
|
</padding>
|
||||||
|
</Button>
|
||||||
|
</children>
|
||||||
|
</HBox>
|
||||||
|
|
||||||
|
<HBox alignment="CENTER_LEFT" spacing="10.0" style="-fx-background-color: white; -fx-background-radius: 14; -fx-border-width: 1; -fx-border-radius: 14; -fx-border-color: #e6e6e6;">
|
||||||
|
<padding>
|
||||||
|
<Insets bottom="10.0" left="15.0" right="15.0" top="10.0" />
|
||||||
|
</padding>
|
||||||
|
<children>
|
||||||
|
<TextField fx:id="txtSearch" promptText="Search staff..." style="-fx-border-width: 0; -fx-background-color: transparent;" HBox.hgrow="ALWAYS">
|
||||||
<font>
|
<font>
|
||||||
<Font size="15.0" />
|
<Font size="15.0" />
|
||||||
</font>
|
</font>
|
||||||
@@ -76,7 +139,8 @@
|
|||||||
<TableColumn fx:id="colCreated" prefWidth="150.0" text="Created" />
|
<TableColumn fx:id="colCreated" prefWidth="150.0" text="Created" />
|
||||||
</columns>
|
</columns>
|
||||||
</TableView>
|
</TableView>
|
||||||
|
</children>
|
||||||
|
</VBox>
|
||||||
|
|
||||||
<Label fx:id="lblStatus" text="" textFill="#64748b" visible="false" managed="true">
|
<Label fx:id="lblStatus" text="" textFill="#64748b" visible="false" managed="true">
|
||||||
<font>
|
<font>
|
||||||
|
|||||||
Reference in New Issue
Block a user