added filters to desktop
This commit is contained in:
@@ -3,16 +3,27 @@ package org.example.petshopdesktop;
|
||||
import javafx.application.Application;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.image.Image;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class PetShopApplication extends Application {
|
||||
@Override
|
||||
public void start(Stage stage) throws IOException {
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(PetShopApplication.class.getResource("login-view.fxml"));
|
||||
Scene scene = new Scene(fxmlLoader.load());
|
||||
stage.setTitle("Pet Shop Manager - Login");
|
||||
stage.setTitle("Leon's Pet Store - Login");
|
||||
|
||||
try {
|
||||
stage.getIcons().add(new Image(Objects.requireNonNull(
|
||||
getClass().getResourceAsStream("/org/example/petshopdesktop/images/leons-pet-store-badge.png")
|
||||
)));
|
||||
} catch (Exception e) {
|
||||
System.err.println("Could not load application icon: " + e.getMessage());
|
||||
}
|
||||
|
||||
stage.setScene(scene);
|
||||
stage.show();
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.api.dto.adoption.AdoptionResponse;
|
||||
import org.example.petshopdesktop.api.dto.common.DropdownOption;
|
||||
import org.example.petshopdesktop.api.endpoints.AdoptionApi;
|
||||
import org.example.petshopdesktop.api.endpoints.DropdownApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.AdoptionDialogController;
|
||||
import org.example.petshopdesktop.models.Adoption;
|
||||
import org.example.petshopdesktop.ui.CalendarPane;
|
||||
@@ -76,6 +78,14 @@ public class AdoptionController {
|
||||
@FXML
|
||||
private TextField txtSearch;
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> cbStatusFilter;
|
||||
|
||||
@FXML
|
||||
private ComboBox<DropdownOption> cbStoreFilter;
|
||||
|
||||
private final java.util.ArrayList<DropdownOption> storeOptions = new java.util.ArrayList<>();
|
||||
|
||||
@FXML
|
||||
private CalendarPane calendarPane;
|
||||
private LocalDate selectedCalendarDate = null;
|
||||
@@ -104,6 +114,17 @@ public class AdoptionController {
|
||||
filteredAdoptions = new FilteredList<>(data, a -> true);
|
||||
TableViewSupport.bindSortedItems(tvAdoptions, filteredAdoptions);
|
||||
|
||||
cbStatusFilter.setItems(FXCollections.observableArrayList("All Statuses", "Pending", "Completed", "Cancelled"));
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
cbStatusFilter.valueProperty().addListener((obs, o, n) -> applyFilterPredicate());
|
||||
|
||||
if (UserSession.getInstance().isAdmin()) {
|
||||
cbStoreFilter.setVisible(true);
|
||||
cbStoreFilter.setManaged(true);
|
||||
loadStoreFilter();
|
||||
}
|
||||
cbStoreFilter.valueProperty().addListener((obs, o, n) -> displayAdoptions());
|
||||
|
||||
displayAdoptions();
|
||||
TableViewSupport.installDoubleClickAction(tvAdoptions, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
@@ -120,7 +141,7 @@ public class AdoptionController {
|
||||
|
||||
calendarPane.setOnDateSelected(date -> {
|
||||
selectedCalendarDate = date;
|
||||
filteredAdoptions.setPredicate(a -> date == null || a.getAdoptionDate().equals(date.toString()));
|
||||
applyFilterPredicate();
|
||||
});
|
||||
|
||||
tvAdoptions.setOnKeyPressed(event -> {
|
||||
@@ -135,6 +156,8 @@ public class AdoptionController {
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
selectedCalendarDate = null;
|
||||
if (filteredAdoptions != null) filteredAdoptions.setPredicate(a -> true);
|
||||
tvAdoptions.getSortOrder().clear();
|
||||
@@ -208,7 +231,7 @@ public class AdoptionController {
|
||||
} else {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Long storeId = UserSession.getInstance().isAdmin() ? null : UserSession.getInstance().getStoreId();
|
||||
Long storeId = selectedStoreId();
|
||||
List<AdoptionResponse> adoptions = AdoptionApi.getInstance().listAdoptions(filter, storeId);
|
||||
List<Adoption> adoptionList = adoptions.stream()
|
||||
.map(this::mapToAdoption)
|
||||
@@ -223,9 +246,7 @@ public class AdoptionController {
|
||||
.filter(d -> d != null)
|
||||
.collect(java.util.stream.Collectors.toSet());
|
||||
calendarPane.setEventDates(dates);
|
||||
if (selectedCalendarDate != null) {
|
||||
filteredAdoptions.setPredicate(a -> a.getAdoptionDate().equals(selectedCalendarDate.toString()));
|
||||
}
|
||||
applyFilterPredicate();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(() -> {
|
||||
@@ -307,6 +328,44 @@ public class AdoptionController {
|
||||
txtSearch.setText("");
|
||||
}
|
||||
|
||||
private void loadStoreFilter() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
List<DropdownOption> stores = DropdownApi.getInstance().getStores();
|
||||
DropdownOption allStores = new DropdownOption();
|
||||
allStores.setLabel("All Stores");
|
||||
Platform.runLater(() -> {
|
||||
storeOptions.clear();
|
||||
storeOptions.addAll(stores);
|
||||
java.util.List<DropdownOption> items = new java.util.ArrayList<>();
|
||||
items.add(allStores);
|
||||
items.addAll(stores);
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList(items));
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException("AdoptionController.loadStoreFilter", e, "Loading store filter");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private Long selectedStoreId() {
|
||||
if (!UserSession.getInstance().isAdmin()) return UserSession.getInstance().getStoreId();
|
||||
DropdownOption selected = cbStoreFilter.getValue();
|
||||
return (selected != null && selected.getId() != null) ? selected.getId() : null;
|
||||
}
|
||||
|
||||
private void applyFilterPredicate() {
|
||||
String selectedStatus = cbStatusFilter.getValue();
|
||||
filteredAdoptions.setPredicate(a -> {
|
||||
boolean dateMatch = selectedCalendarDate == null
|
||||
|| a.getAdoptionDate().equals(selectedCalendarDate.toString());
|
||||
boolean statusMatch = selectedStatus == null || selectedStatus.equals("All Statuses")
|
||||
|| a.getAdoptionStatus().equalsIgnoreCase(selectedStatus);
|
||||
return dateMatch && statusMatch;
|
||||
});
|
||||
}
|
||||
|
||||
private Adoption mapToAdoption(AdoptionResponse response) {
|
||||
return new Adoption(
|
||||
response.getAdoptionId().intValue(),
|
||||
|
||||
@@ -16,7 +16,9 @@ import javafx.stage.Stage;
|
||||
|
||||
import org.example.petshopdesktop.DTOs.AppointmentDTO;
|
||||
import org.example.petshopdesktop.api.dto.appointment.AppointmentResponse;
|
||||
import org.example.petshopdesktop.api.dto.common.DropdownOption;
|
||||
import org.example.petshopdesktop.api.endpoints.AppointmentApi;
|
||||
import org.example.petshopdesktop.api.endpoints.DropdownApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.AppointmentDialogController;
|
||||
import org.example.petshopdesktop.ui.CalendarPane;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
@@ -52,6 +54,11 @@ public class AppointmentController {
|
||||
|
||||
@FXML private TextField txtSearch;
|
||||
|
||||
@FXML private ComboBox<String> cbStatusFilter;
|
||||
@FXML private ComboBox<DropdownOption> cbStoreFilter;
|
||||
|
||||
private final java.util.ArrayList<DropdownOption> storeOptions = new java.util.ArrayList<>();
|
||||
|
||||
@FXML private CalendarPane calendarPane;
|
||||
private LocalDate selectedCalendarDate = null;
|
||||
|
||||
@@ -83,6 +90,17 @@ public class AppointmentController {
|
||||
btnMyAppointments.setManaged(true);
|
||||
}
|
||||
|
||||
cbStatusFilter.setItems(FXCollections.observableArrayList("All Statuses", "Booked", "Completed", "Missed", "Cancelled"));
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
cbStatusFilter.valueProperty().addListener((obs, o, n) -> applyFilterPredicate());
|
||||
|
||||
if (UserSession.getInstance().isAdmin()) {
|
||||
cbStoreFilter.setVisible(true);
|
||||
cbStoreFilter.setManaged(true);
|
||||
loadStoreFilter();
|
||||
}
|
||||
cbStoreFilter.valueProperty().addListener((obs, o, n) -> loadAppointments());
|
||||
|
||||
if (txtSearch != null) {
|
||||
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
||||
}
|
||||
@@ -105,7 +123,7 @@ public class AppointmentController {
|
||||
|
||||
calendarPane.setOnDateSelected(date -> {
|
||||
selectedCalendarDate = date;
|
||||
filtered.setPredicate(apt -> date == null || apt.getAppointmentDate().equals(date.toString()));
|
||||
applyFilterPredicate();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -117,7 +135,7 @@ public class AppointmentController {
|
||||
private void loadAppointments(){
|
||||
new Thread(() -> {
|
||||
try{
|
||||
Long storeId = UserSession.getInstance().isAdmin() ? null : UserSession.getInstance().getStoreId();
|
||||
Long storeId = selectedStoreId();
|
||||
Long employeeId = btnMyAppointments.isSelected() ? UserSession.getInstance().getEmployeeId() : null;
|
||||
List<AppointmentResponse> responses = AppointmentApi.getInstance().listAppointments(null, storeId, employeeId);
|
||||
List<AppointmentDTO> appointmentDTOs = responses.stream()
|
||||
@@ -133,9 +151,7 @@ public class AppointmentController {
|
||||
.filter(d -> d != null)
|
||||
.collect(java.util.stream.Collectors.toSet());
|
||||
calendarPane.setEventDates(dates);
|
||||
if (selectedCalendarDate != null) {
|
||||
filtered.setPredicate(apt -> apt.getAppointmentDate().equals(selectedCalendarDate.toString()));
|
||||
}
|
||||
applyFilterPredicate();
|
||||
});
|
||||
}catch(Exception e){
|
||||
Platform.runLater(() -> {
|
||||
@@ -153,7 +169,7 @@ public class AppointmentController {
|
||||
String query = text == null || text.trim().isEmpty() ? null : text.trim();
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Long storeId = UserSession.getInstance().isAdmin() ? null : UserSession.getInstance().getStoreId();
|
||||
Long storeId = selectedStoreId();
|
||||
Long employeeId = btnMyAppointments.isSelected() ? UserSession.getInstance().getEmployeeId() : null;
|
||||
List<AppointmentResponse> responses = AppointmentApi.getInstance().listAppointments(query, storeId, employeeId);
|
||||
List<AppointmentDTO> appointmentDTOs = responses.stream()
|
||||
@@ -169,9 +185,7 @@ public class AppointmentController {
|
||||
.filter(d -> d != null)
|
||||
.collect(java.util.stream.Collectors.toSet());
|
||||
calendarPane.setEventDates(dates);
|
||||
if (selectedCalendarDate != null) {
|
||||
filtered.setPredicate(apt -> apt.getAppointmentDate().equals(selectedCalendarDate.toString()));
|
||||
}
|
||||
applyFilterPredicate();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(() -> {
|
||||
@@ -188,6 +202,8 @@ public class AppointmentController {
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
selectedCalendarDate = null;
|
||||
filtered.setPredicate(a -> true);
|
||||
tvAppointments.getSortOrder().clear();
|
||||
@@ -291,6 +307,44 @@ public class AppointmentController {
|
||||
}
|
||||
}
|
||||
|
||||
private void loadStoreFilter() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
List<DropdownOption> stores = DropdownApi.getInstance().getStores();
|
||||
DropdownOption allStores = new DropdownOption();
|
||||
allStores.setLabel("All Stores");
|
||||
Platform.runLater(() -> {
|
||||
storeOptions.clear();
|
||||
storeOptions.addAll(stores);
|
||||
java.util.List<DropdownOption> items = new java.util.ArrayList<>();
|
||||
items.add(allStores);
|
||||
items.addAll(stores);
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList(items));
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException("AppointmentController.loadStoreFilter", e, "Loading store filter");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private Long selectedStoreId() {
|
||||
if (!UserSession.getInstance().isAdmin()) return UserSession.getInstance().getStoreId();
|
||||
DropdownOption selected = cbStoreFilter.getValue();
|
||||
return (selected != null && selected.getId() != null) ? selected.getId() : null;
|
||||
}
|
||||
|
||||
private void applyFilterPredicate() {
|
||||
String selectedStatus = cbStatusFilter.getValue();
|
||||
filtered.setPredicate(apt -> {
|
||||
boolean dateMatch = selectedCalendarDate == null
|
||||
|| apt.getAppointmentDate().equals(selectedCalendarDate.toString());
|
||||
boolean statusMatch = selectedStatus == null || selectedStatus.equals("All Statuses")
|
||||
|| apt.getAppointmentStatus().equalsIgnoreCase(selectedStatus);
|
||||
return dateMatch && statusMatch;
|
||||
});
|
||||
}
|
||||
|
||||
private void showAlert(String title, String msg){
|
||||
Alert alert = new Alert(Alert.AlertType.INFORMATION);
|
||||
alert.setTitle(title);
|
||||
|
||||
@@ -49,6 +49,9 @@ public class CustomerAccountsController {
|
||||
@FXML
|
||||
private TextField txtSearchCustomer;
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> cbStatusFilter;
|
||||
|
||||
@FXML
|
||||
private Button btnEditCustomer;
|
||||
|
||||
@@ -82,6 +85,10 @@ public class CustomerAccountsController {
|
||||
btnEditCustomer.setDisable(newVal == null));
|
||||
btnEditCustomer.setDisable(true);
|
||||
|
||||
cbStatusFilter.setItems(FXCollections.observableArrayList("All Statuses", "Active", "Inactive"));
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
cbStatusFilter.valueProperty().addListener((obs, o, n) -> applyCustomerFilter(txtSearchCustomer.getText()));
|
||||
|
||||
txtSearchCustomer.textProperty().addListener((obs, o, n) -> applyCustomerFilter(n));
|
||||
|
||||
refresh();
|
||||
@@ -90,6 +97,7 @@ public class CustomerAccountsController {
|
||||
@FXML
|
||||
void btnRefreshClicked(ActionEvent event) {
|
||||
txtSearchCustomer.clear();
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
TableViewSupport.clearSort(tvCustomers);
|
||||
refresh();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
@@ -154,16 +162,19 @@ public class CustomerAccountsController {
|
||||
|
||||
private void applyCustomerFilter(String text) {
|
||||
String q = text == null ? "" : text.trim().toLowerCase();
|
||||
if (q.isEmpty()) {
|
||||
filteredCustomers.setPredicate(a -> true);
|
||||
return;
|
||||
}
|
||||
filteredCustomers.setPredicate(a ->
|
||||
safe(a.getUsername()).contains(q)
|
||||
|| safe(a.getFullName()).contains(q)
|
||||
|| safe(a.getEmail()).contains(q)
|
||||
|| safe(a.getPhone()).contains(q)
|
||||
);
|
||||
String selectedStatus = cbStatusFilter.getValue();
|
||||
filteredCustomers.setPredicate(a -> {
|
||||
boolean textMatch = q.isEmpty()
|
||||
|| safe(a.getUsername()).contains(q)
|
||||
|| safe(a.getFullName()).contains(q)
|
||||
|| safe(a.getEmail()).contains(q)
|
||||
|| safe(a.getPhone()).contains(q);
|
||||
boolean active = Boolean.TRUE.equals(a.getActive());
|
||||
boolean statusMatch = selectedStatus == null || selectedStatus.equals("All Statuses")
|
||||
|| (selectedStatus.equals("Active") && active)
|
||||
|| (selectedStatus.equals("Inactive") && !active);
|
||||
return textMatch && statusMatch;
|
||||
});
|
||||
}
|
||||
|
||||
private static String safe(String v) {
|
||||
|
||||
@@ -12,7 +12,9 @@ import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.stage.Modality;
|
||||
import org.example.petshopdesktop.auth.UserSession;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.api.dto.common.DropdownOption;
|
||||
import org.example.petshopdesktop.api.dto.inventory.InventoryResponse;
|
||||
import org.example.petshopdesktop.api.endpoints.DropdownApi;
|
||||
import org.example.petshopdesktop.api.endpoints.InventoryApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.InventoryDialogController;
|
||||
import org.example.petshopdesktop.models.Inventory;
|
||||
@@ -63,6 +65,11 @@ public class InventoryController {
|
||||
@FXML
|
||||
private TextField txtSearch;
|
||||
|
||||
@FXML
|
||||
private ComboBox<DropdownOption> cbStoreFilter;
|
||||
|
||||
private final java.util.ArrayList<DropdownOption> storeOptions = new java.util.ArrayList<>();
|
||||
|
||||
private ObservableList<Inventory> data = FXCollections.observableArrayList();
|
||||
|
||||
//Determines if in add/edit mode
|
||||
@@ -81,6 +88,13 @@ public class InventoryController {
|
||||
colQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
|
||||
colStoreName.setCellValueFactory(new PropertyValueFactory<>("storeName"));
|
||||
|
||||
if (UserSession.getInstance().isAdmin()) {
|
||||
cbStoreFilter.setVisible(true);
|
||||
cbStoreFilter.setManaged(true);
|
||||
loadStoreFilter();
|
||||
}
|
||||
cbStoreFilter.valueProperty().addListener((obs, o, n) -> displayInventory());
|
||||
|
||||
displayInventory();
|
||||
TableViewSupport.installDoubleClickAction(tvInventory, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
@@ -108,6 +122,7 @@ public class InventoryController {
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
tvInventory.getSortOrder().clear();
|
||||
displayInventory();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
@@ -172,7 +187,7 @@ public class InventoryController {
|
||||
} else {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Long storeId = UserSession.getInstance().isAdmin() ? null : UserSession.getInstance().getStoreId();
|
||||
Long storeId = selectedStoreId();
|
||||
List<InventoryResponse> inventories = InventoryApi.getInstance().listInventory(filter, storeId);
|
||||
List<Inventory> inventoryList = inventories.stream()
|
||||
.map(this::mapToInventory)
|
||||
@@ -198,7 +213,7 @@ public class InventoryController {
|
||||
private void displayInventory() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Long storeId = UserSession.getInstance().isAdmin() ? null : UserSession.getInstance().getStoreId();
|
||||
Long storeId = selectedStoreId();
|
||||
List<InventoryResponse> inventories = InventoryApi.getInstance().listInventory(null, storeId);
|
||||
List<Inventory> inventoryList = inventories.stream()
|
||||
.map(this::mapToInventory)
|
||||
@@ -253,6 +268,33 @@ public class InventoryController {
|
||||
txtSearch.setText("");
|
||||
}
|
||||
|
||||
private void loadStoreFilter() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
List<DropdownOption> stores = DropdownApi.getInstance().getStores();
|
||||
DropdownOption allStores = new DropdownOption();
|
||||
allStores.setLabel("All Stores");
|
||||
Platform.runLater(() -> {
|
||||
storeOptions.clear();
|
||||
storeOptions.addAll(stores);
|
||||
java.util.List<DropdownOption> items = new java.util.ArrayList<>();
|
||||
items.add(allStores);
|
||||
items.addAll(stores);
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList(items));
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException("InventoryController.loadStoreFilter", e, "Loading store filter");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private Long selectedStoreId() {
|
||||
if (!UserSession.getInstance().isAdmin()) return UserSession.getInstance().getStoreId();
|
||||
DropdownOption selected = cbStoreFilter.getValue();
|
||||
return (selected != null && selected.getId() != null) ? selected.getId() : null;
|
||||
}
|
||||
|
||||
private Inventory mapToInventory(InventoryResponse response) {
|
||||
return new Inventory(
|
||||
response.getInventoryId().intValue(),
|
||||
|
||||
@@ -113,6 +113,9 @@ public class MainLayoutController {
|
||||
@FXML
|
||||
private Button btnRemoveAvatar;
|
||||
|
||||
@FXML
|
||||
private Button btnRefreshAvatar;
|
||||
|
||||
@FXML
|
||||
private Label lblUsername;
|
||||
|
||||
@@ -253,6 +256,29 @@ public class MainLayoutController {
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnRefreshAvatarClicked(ActionEvent event) {
|
||||
btnRefreshAvatar.setDisable(true);
|
||||
new Thread(() -> {
|
||||
try {
|
||||
UserInfoResponse userInfo = AuthApi.getInstance().getCurrentUser();
|
||||
String displayName = userInfo.getFullName() == null || userInfo.getFullName().isBlank()
|
||||
? UserSession.getInstance().getUsername()
|
||||
: userInfo.getFullName();
|
||||
Image avatarImage = loadAvatarImage(userInfo.getAvatarUrl());
|
||||
Platform.runLater(() -> {
|
||||
UserSession.getInstance().setAvatarUrl(userInfo.getAvatarUrl());
|
||||
renderAvatar(displayName, avatarImage);
|
||||
btnRemoveAvatar.setDisable(userInfo.getAvatarUrl() == null || userInfo.getAvatarUrl().isBlank());
|
||||
btnRefreshAvatar.setDisable(false);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(() -> btnRefreshAvatar.setDisable(false));
|
||||
ActivityLogger.getInstance().logException("MainLayoutController.btnRefreshAvatarClicked", e, "Refreshing avatar");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnRemoveAvatarClicked(ActionEvent event) {
|
||||
try {
|
||||
|
||||
@@ -86,18 +86,20 @@ public class PetController {
|
||||
@FXML
|
||||
private ComboBox<String> cbStatusFilter;
|
||||
|
||||
@FXML
|
||||
private ComboBox<DropdownOption> cbStoreFilter;
|
||||
|
||||
private final java.util.ArrayList<DropdownOption> storeOptions = new java.util.ArrayList<>();
|
||||
|
||||
@FXML
|
||||
private TextField txtSearch;
|
||||
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
if (cbSpeciesFilter != null) {
|
||||
cbSpeciesFilter.getSelectionModel().selectFirst();
|
||||
}
|
||||
if (cbStatusFilter != null) {
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
}
|
||||
if (cbSpeciesFilter != null) cbSpeciesFilter.getSelectionModel().selectFirst();
|
||||
if (cbStatusFilter != null) cbStatusFilter.getSelectionModel().selectFirst();
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
tvPets.getSortOrder().clear();
|
||||
displayPets();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
@@ -194,6 +196,13 @@ public class PetController {
|
||||
cbStatusFilter.setItems(FXCollections.observableArrayList("All Statuses", "Available", "Adopted", "Owned", "Pending"));
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
|
||||
if (UserSession.getInstance().isAdmin()) {
|
||||
cbStoreFilter.setVisible(true);
|
||||
cbStoreFilter.setManaged(true);
|
||||
loadStoreFilter();
|
||||
}
|
||||
cbStoreFilter.valueProperty().addListener((obs, o, n) -> applyFilters());
|
||||
|
||||
displayPets();
|
||||
TableViewSupport.installDoubleClickAction(tvPets, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
@@ -229,7 +238,7 @@ public class PetController {
|
||||
} else {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Long storeId = UserSession.getInstance().isAdmin() ? null : UserSession.getInstance().getStoreId();
|
||||
Long storeId = selectedStoreId();
|
||||
List<PetResponse> pets = PetApi.getInstance().listPets(filter, species, status, storeId);
|
||||
List<Pet> petList = pets.stream()
|
||||
.map(this::mapToPet)
|
||||
@@ -255,7 +264,7 @@ public class PetController {
|
||||
private void displayPets() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Long storeId = UserSession.getInstance().isAdmin() ? null : UserSession.getInstance().getStoreId();
|
||||
Long storeId = selectedStoreId();
|
||||
List<PetResponse> pets = PetApi.getInstance().listPets(null, selectedSpecies(), selectedStatus(), storeId);
|
||||
List<Pet> petList = pets.stream()
|
||||
.map(this::mapToPet)
|
||||
@@ -281,6 +290,33 @@ public class PetController {
|
||||
displayFilteredPet(txtSearch.getText());
|
||||
}
|
||||
|
||||
private void loadStoreFilter() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
List<DropdownOption> stores = DropdownApi.getInstance().getStores();
|
||||
DropdownOption allStores = new DropdownOption();
|
||||
allStores.setLabel("All Stores");
|
||||
Platform.runLater(() -> {
|
||||
storeOptions.clear();
|
||||
storeOptions.addAll(stores);
|
||||
java.util.List<DropdownOption> items = new java.util.ArrayList<>();
|
||||
items.add(allStores);
|
||||
items.addAll(stores);
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList(items));
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException("PetController.loadStoreFilter", e, "Loading store filter");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private Long selectedStoreId() {
|
||||
if (!UserSession.getInstance().isAdmin()) return UserSession.getInstance().getStoreId();
|
||||
DropdownOption selected = cbStoreFilter.getValue();
|
||||
return (selected != null && selected.getId() != null) ? selected.getId() : null;
|
||||
}
|
||||
|
||||
private void loadSpeciesFilter() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
|
||||
@@ -146,6 +146,20 @@ public class SaleController {
|
||||
@FXML
|
||||
private TextField txtSearch;
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> cbFilterPayment;
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> cbFilterRefundStatus;
|
||||
|
||||
@FXML
|
||||
private ComboBox<DropdownOption> cbFilterCustomer;
|
||||
|
||||
@FXML
|
||||
private ComboBox<DropdownOption> cbStoreFilter;
|
||||
|
||||
private final java.util.ArrayList<DropdownOption> storeOptions = new java.util.ArrayList<>();
|
||||
|
||||
@FXML
|
||||
private ComboBox<DropdownOption> cbCustomer;
|
||||
|
||||
@@ -249,6 +263,24 @@ public class SaleController {
|
||||
TableViewSupport.bindSortedItems(tvSales, filteredSales);
|
||||
TableViewSupport.installDoubleClickAction(tvSales, selected -> openSaleDetailDialog(selected.getSaleId()));
|
||||
|
||||
if (UserSession.getInstance().isAdmin()) {
|
||||
cbStoreFilter.setVisible(true);
|
||||
cbStoreFilter.setManaged(true);
|
||||
loadStoreFilter();
|
||||
}
|
||||
cbStoreFilter.valueProperty().addListener((obs, o, n) -> refreshSales(false));
|
||||
|
||||
cbFilterPayment.setItems(FXCollections.observableArrayList("All Payments", "Cash", "Card"));
|
||||
cbFilterPayment.getSelectionModel().selectFirst();
|
||||
cbFilterPayment.valueProperty().addListener((obs, o, n) -> applySalesFilter(txtSearch.getText()));
|
||||
|
||||
cbFilterRefundStatus.setItems(FXCollections.observableArrayList("All Status", "Sales Only", "Refunds Only"));
|
||||
cbFilterRefundStatus.getSelectionModel().selectFirst();
|
||||
cbFilterRefundStatus.valueProperty().addListener((obs, o, n) -> applySalesFilter(txtSearch.getText()));
|
||||
|
||||
loadCustomerFilter();
|
||||
cbFilterCustomer.valueProperty().addListener((obs, o, n) -> applySalesFilter(txtSearch.getText()));
|
||||
|
||||
txtSearch.textProperty().addListener((obs, oldVal, newVal) -> applySalesFilter(newVal));
|
||||
tvSales.widthProperty().addListener((obs, oldWidth, newWidth) -> updateSalesColumnWidths(newWidth.doubleValue()));
|
||||
tvCart.widthProperty().addListener((obs, oldWidth, newWidth) -> updateCartColumnWidths(newWidth.doubleValue()));
|
||||
@@ -404,8 +436,7 @@ public class SaleController {
|
||||
Task<List<SaleLineItem>> task = new Task<List<SaleLineItem>>() {
|
||||
@Override
|
||||
protected List<SaleLineItem> call() throws Exception {
|
||||
Long storeId = UserSession.getInstance().isAdmin() ? null : UserSession.getInstance().getStoreId();
|
||||
List<SaleResponse> sales = SaleApi.getInstance().listAllSales(null, storeId);
|
||||
List<SaleResponse> sales = SaleApi.getInstance().listAllSales(null, selectedStoreId());
|
||||
sales.sort(Comparator.comparing(SaleResponse::getSaleDate, Comparator.nullsLast(Comparator.reverseOrder()))
|
||||
.thenComparing(SaleResponse::getSaleId, Comparator.nullsLast(Comparator.reverseOrder())));
|
||||
List<SaleLineItem> lineItems = new ArrayList<>();
|
||||
@@ -465,6 +496,10 @@ public class SaleController {
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
cbFilterPayment.getSelectionModel().selectFirst();
|
||||
cbFilterRefundStatus.getSelectionModel().selectFirst();
|
||||
cbFilterCustomer.getSelectionModel().selectFirst();
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
TableViewSupport.clearSort(tvSales);
|
||||
refreshSales(false);
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
@@ -942,25 +977,83 @@ public class SaleController {
|
||||
|
||||
private void applySalesFilter(String filter) {
|
||||
String f = filter == null ? "" : filter.trim().toLowerCase();
|
||||
if (f.isEmpty()) {
|
||||
filteredSales.setPredicate(s -> true);
|
||||
return;
|
||||
}
|
||||
String selectedPayment = cbFilterPayment.getValue();
|
||||
String selectedStatus = cbFilterRefundStatus.getValue();
|
||||
DropdownOption selectedCustomer = cbFilterCustomer.getValue();
|
||||
|
||||
filteredSales.setPredicate(s ->
|
||||
String.valueOf(s.getSaleId()).contains(f)
|
||||
filteredSales.setPredicate(s -> {
|
||||
boolean textMatch = f.isEmpty()
|
||||
|| String.valueOf(s.getSaleId()).contains(f)
|
||||
|| safe(s.getSaleDate()).contains(f)
|
||||
|| safe(s.getEmployeeName()).contains(f)
|
||||
|| safe(s.getCustomerName()).contains(f)
|
||||
|| safe(s.getItemName()).contains(f)
|
||||
|| safe(s.getPaymentMethod()).contains(f)
|
||||
);
|
||||
|| safe(s.getPaymentMethod()).contains(f);
|
||||
|
||||
boolean paymentMatch = selectedPayment == null || selectedPayment.equals("All Payments")
|
||||
|| safe(s.getPaymentMethod()).equals(selectedPayment.toLowerCase());
|
||||
|
||||
boolean refundMatch = selectedStatus == null || selectedStatus.equals("All Status")
|
||||
|| (selectedStatus.equals("Sales Only") && !s.isRefund())
|
||||
|| (selectedStatus.equals("Refunds Only") && s.isRefund());
|
||||
|
||||
boolean customerMatch = selectedCustomer == null || selectedCustomer.getId() == null
|
||||
|| safe(s.getCustomerName()).equals(safe(selectedCustomer.getLabel()));
|
||||
|
||||
return textMatch && paymentMatch && refundMatch && customerMatch;
|
||||
});
|
||||
}
|
||||
|
||||
private static String safe(String v) {
|
||||
return v == null ? "" : v.toLowerCase();
|
||||
}
|
||||
|
||||
private void loadCustomerFilter() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
List<DropdownOption> customers = DropdownApi.getInstance().getCustomers();
|
||||
DropdownOption allCustomers = new DropdownOption();
|
||||
allCustomers.setLabel("All Customers");
|
||||
Platform.runLater(() -> {
|
||||
java.util.List<DropdownOption> items = new java.util.ArrayList<>();
|
||||
items.add(allCustomers);
|
||||
items.addAll(customers);
|
||||
cbFilterCustomer.setItems(FXCollections.observableArrayList(items));
|
||||
cbFilterCustomer.getSelectionModel().selectFirst();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException("SaleController.loadCustomerFilter", e, "Loading customer filter");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void loadStoreFilter() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
List<DropdownOption> stores = DropdownApi.getInstance().getStores();
|
||||
DropdownOption allStores = new DropdownOption();
|
||||
allStores.setLabel("All Stores");
|
||||
Platform.runLater(() -> {
|
||||
storeOptions.clear();
|
||||
storeOptions.addAll(stores);
|
||||
java.util.List<DropdownOption> items = new java.util.ArrayList<>();
|
||||
items.add(allStores);
|
||||
items.addAll(stores);
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList(items));
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException("SaleController.loadStoreFilter", e, "Loading store filter");
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private Long selectedStoreId() {
|
||||
if (!UserSession.getInstance().isAdmin()) return UserSession.getInstance().getStoreId();
|
||||
DropdownOption selected = cbStoreFilter.getValue();
|
||||
return (selected != null && selected.getId() != null) ? selected.getId() : null;
|
||||
}
|
||||
|
||||
private void showError(String title, String message) {
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setTitle(title);
|
||||
|
||||
@@ -34,6 +34,8 @@ public class StaffAccountsController {
|
||||
@FXML private TableColumn<EmployeeResponse, String> colStatus;
|
||||
@FXML private TableColumn<EmployeeResponse, Object> colCreated;
|
||||
@FXML private TextField txtSearch;
|
||||
@FXML private ComboBox<String> cbRoleFilter;
|
||||
@FXML private ComboBox<String> cbStatusFilter;
|
||||
@FXML private Button btnRefresh;
|
||||
@FXML private Button btnCreateAccount;
|
||||
@FXML private Button btnEditAccount;
|
||||
@@ -66,6 +68,14 @@ public class StaffAccountsController {
|
||||
btnEditAccount.setDisable(newVal == null));
|
||||
btnEditAccount.setDisable(true);
|
||||
|
||||
cbRoleFilter.setItems(FXCollections.observableArrayList("All Roles", "Admin", "Staff"));
|
||||
cbRoleFilter.getSelectionModel().selectFirst();
|
||||
cbRoleFilter.valueProperty().addListener((obs, o, n) -> applyStaffFilter(txtSearch.getText()));
|
||||
|
||||
cbStatusFilter.setItems(FXCollections.observableArrayList("All Statuses", "Active", "Inactive"));
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
cbStatusFilter.valueProperty().addListener((obs, o, n) -> applyStaffFilter(txtSearch.getText()));
|
||||
|
||||
txtSearch.textProperty().addListener((obs, o, n) -> applyStaffFilter(n));
|
||||
|
||||
refresh();
|
||||
@@ -74,6 +84,8 @@ public class StaffAccountsController {
|
||||
@FXML
|
||||
void btnRefreshClicked(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
cbRoleFilter.getSelectionModel().selectFirst();
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
TableViewSupport.clearSort(tvStaff);
|
||||
refresh();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
@@ -166,18 +178,24 @@ public class StaffAccountsController {
|
||||
|
||||
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.getFullName()).contains(q)
|
||||
|| safe(a.getEmail()).contains(q)
|
||||
|| safe(a.getPhone()).contains(q)
|
||||
|| safe(a.getRole()).contains(q)
|
||||
|| safe(a.getStaffRole()).contains(q)
|
||||
);
|
||||
String selectedRole = cbRoleFilter.getValue();
|
||||
String selectedStatus = cbStatusFilter.getValue();
|
||||
filteredStaff.setPredicate(a -> {
|
||||
boolean textMatch = q.isEmpty()
|
||||
|| safe(a.getUsername()).contains(q)
|
||||
|| safe(a.getFullName()).contains(q)
|
||||
|| safe(a.getEmail()).contains(q)
|
||||
|| safe(a.getPhone()).contains(q)
|
||||
|| safe(a.getRole()).contains(q)
|
||||
|| safe(a.getStaffRole()).contains(q);
|
||||
boolean active = Boolean.TRUE.equals(a.getActive());
|
||||
boolean statusMatch = selectedStatus == null || selectedStatus.equals("All Statuses")
|
||||
|| (selectedStatus.equals("Active") && active)
|
||||
|| (selectedStatus.equals("Inactive") && !active);
|
||||
boolean roleMatch = selectedRole == null || selectedRole.equals("All Roles")
|
||||
|| safe(a.getRole()).equals(selectedRole.toLowerCase());
|
||||
return textMatch && statusMatch && roleMatch;
|
||||
});
|
||||
}
|
||||
|
||||
private static String safe(String v) {
|
||||
|
||||
@@ -59,14 +59,26 @@
|
||||
<Insets bottom="6.0" left="10.0" right="10.0" top="6.0" />
|
||||
</padding>
|
||||
</Button>
|
||||
<Button fx:id="btnRemoveAvatar" mnemonicParsing="false" onAction="#btnRemoveAvatarClicked" style="-fx-background-color: transparent; -fx-border-color: rgba(226,232,240,0.35); -fx-border-radius: 8; -fx-background-radius: 8; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Remove" textFill="#cbd5e1">
|
||||
<font>
|
||||
<Font name="System" size="11.0" />
|
||||
</font>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="10.0" right="10.0" top="5.0" />
|
||||
</padding>
|
||||
</Button>
|
||||
<HBox spacing="6.0">
|
||||
<children>
|
||||
<Button fx:id="btnRemoveAvatar" mnemonicParsing="false" onAction="#btnRemoveAvatarClicked" style="-fx-background-color: transparent; -fx-border-color: rgba(226,232,240,0.35); -fx-border-radius: 8; -fx-background-radius: 8; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Remove" textFill="#cbd5e1">
|
||||
<font>
|
||||
<Font name="System" size="11.0" />
|
||||
</font>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="10.0" right="10.0" top="5.0" />
|
||||
</padding>
|
||||
</Button>
|
||||
<Button fx:id="btnRefreshAvatar" mnemonicParsing="false" onAction="#btnRefreshAvatarClicked" style="-fx-background-color: transparent; -fx-border-color: rgba(226,232,240,0.35); -fx-border-radius: 8; -fx-background-radius: 8; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="↻" textFill="#cbd5e1">
|
||||
<font>
|
||||
<Font name="System" size="13.0" />
|
||||
</font>
|
||||
<padding>
|
||||
<Insets bottom="5.0" left="8.0" right="8.0" top="5.0" />
|
||||
</padding>
|
||||
</Button>
|
||||
</children>
|
||||
</HBox>
|
||||
</children>
|
||||
</VBox>
|
||||
</children>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TableColumn?>
|
||||
<?import javafx.scene.control.TableView?>
|
||||
@@ -72,6 +73,8 @@
|
||||
<Font size="15.0" />
|
||||
</font>
|
||||
</TextField>
|
||||
<ComboBox fx:id="cbStatusFilter" prefWidth="150.0" promptText="All Statuses" />
|
||||
<ComboBox fx:id="cbStoreFilter" prefWidth="150.0" promptText="All Stores" visible="false" managed="false" />
|
||||
</children>
|
||||
</HBox>
|
||||
<CalendarPane fx:id="calendarPane" maxWidth="Infinity" />
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.ToggleButton?>
|
||||
<?import javafx.scene.control.TableColumn?>
|
||||
@@ -81,6 +82,8 @@
|
||||
<Font size="15.0" />
|
||||
</font>
|
||||
</TextField>
|
||||
<ComboBox fx:id="cbStatusFilter" prefWidth="150.0" promptText="All Statuses" />
|
||||
<ComboBox fx:id="cbStoreFilter" prefWidth="150.0" promptText="All Stores" visible="false" managed="false" />
|
||||
</children>
|
||||
</HBox>
|
||||
<CalendarPane fx:id="calendarPane" maxWidth="Infinity" />
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TableColumn?>
|
||||
<?import javafx.scene.control.TableView?>
|
||||
@@ -62,6 +63,7 @@
|
||||
<Font size="15.0" />
|
||||
</font>
|
||||
</TextField>
|
||||
<ComboBox fx:id="cbStatusFilter" prefWidth="140.0" promptText="All Statuses" />
|
||||
</children>
|
||||
</HBox>
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TableColumn?>
|
||||
<?import javafx.scene.control.TableView?>
|
||||
@@ -71,6 +72,7 @@
|
||||
<Font size="15.0" />
|
||||
</font>
|
||||
</TextField>
|
||||
<ComboBox fx:id="cbStoreFilter" prefWidth="150.0" promptText="All Stores" visible="false" managed="false" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="lblStatus" text="" textFill="#64748b" visible="false" managed="true">
|
||||
|
||||
@@ -75,6 +75,7 @@
|
||||
</TextField>
|
||||
<ComboBox fx:id="cbSpeciesFilter" prefWidth="150.0" promptText="Species" />
|
||||
<ComboBox fx:id="cbStatusFilter" prefWidth="150.0" promptText="Status" />
|
||||
<ComboBox fx:id="cbStoreFilter" prefWidth="150.0" promptText="All Stores" visible="false" managed="false" />
|
||||
</children>
|
||||
</HBox>
|
||||
<Label fx:id="lblStatus" text="" textFill="#64748b" visible="false" managed="true">
|
||||
|
||||
@@ -210,6 +210,10 @@
|
||||
<Font size="15.0" />
|
||||
</font>
|
||||
</TextField>
|
||||
<ComboBox fx:id="cbFilterPayment" prefWidth="140.0" promptText="All Payments" />
|
||||
<ComboBox fx:id="cbFilterRefundStatus" prefWidth="140.0" promptText="All Status" />
|
||||
<ComboBox fx:id="cbFilterCustomer" prefWidth="160.0" promptText="All Customers" />
|
||||
<ComboBox fx:id="cbStoreFilter" prefWidth="150.0" promptText="All Stores" visible="false" managed="false" />
|
||||
</children>
|
||||
</HBox>
|
||||
<TableView fx:id="tvSales" prefHeight="270.0" style="-fx-background-color: white; -fx-background-radius: 12; -fx-padding: 2;" VBox.vgrow="ALWAYS">
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TableColumn?>
|
||||
<?import javafx.scene.control.TableView?>
|
||||
@@ -70,6 +71,8 @@
|
||||
<Font size="15.0" />
|
||||
</font>
|
||||
</TextField>
|
||||
<ComboBox fx:id="cbRoleFilter" prefWidth="120.0" promptText="All Roles" />
|
||||
<ComboBox fx:id="cbStatusFilter" prefWidth="130.0" promptText="All Statuses" />
|
||||
</children>
|
||||
</HBox>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user