Fix sales UI

This commit is contained in:
2026-04-10 08:20:25 -06:00
parent 588ddd7fec
commit d412490706
2 changed files with 240 additions and 156 deletions

View File

@@ -150,12 +150,16 @@ public class SaleController {
}
private void setupTables() {
tvCart.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
tvCart.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
tvCart.setFixedCellSize(34);
colCartProduct.setCellValueFactory(new PropertyValueFactory<>("prodName"));
colCartQty.setCellValueFactory(new PropertyValueFactory<>("quantity"));
colCartUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice"));
colCartTotal.setCellValueFactory(new PropertyValueFactory<>("total"));
colCartProduct.setMinWidth(190);
colCartQty.setMinWidth(70);
colCartUnitPrice.setMinWidth(90);
colCartTotal.setMinWidth(90);
TableViewSupport.applyCurrencyColumn(colCartUnitPrice);
TableViewSupport.applyCurrencyColumn(colCartTotal);
tvCart.setItems(cartItems);
@@ -171,6 +175,14 @@ public class SaleController {
colSaleUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice"));
colSaleTotal.setCellValueFactory(new PropertyValueFactory<>("total"));
colSalePaymentType.setCellValueFactory(new PropertyValueFactory<>("paymentMethod"));
colSaleId.setMinWidth(50);
colSaleDate.setMinWidth(150);
colEmployeeName.setMinWidth(150);
colServiceProduct.setMinWidth(260);
colSaleQuantity.setMinWidth(55);
colSaleUnitPrice.setMinWidth(100);
colSaleTotal.setMinWidth(100);
colSalePaymentType.setMinWidth(95);
TableViewSupport.applyCurrencyColumn(colSaleUnitPrice);
TableViewSupport.applyCurrencyColumn(colSaleTotal);
@@ -179,6 +191,12 @@ public class SaleController {
TableViewSupport.installDoubleClickAction(tvSales, selected -> openSaleDetailDialog(selected.getSaleId()));
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()));
Platform.runLater(() -> {
updateSalesColumnWidths(tvSales.getWidth());
updateCartColumnWidths(tvCart.getWidth());
});
}
private void setupCreateSale() {
@@ -543,6 +561,58 @@ public class SaleController {
lblCartTotal.setText(currency.format(total));
}
private void updateSalesColumnWidths(double tableWidth) {
double available = Math.max(tableWidth - 28.0, 0.0);
double baseWidth = 1125.0;
if (available <= 0) {
return;
}
if (available <= baseWidth) {
colSaleId.setPrefWidth(60.0);
colSaleDate.setPrefWidth(170.0);
colEmployeeName.setPrefWidth(160.0);
colServiceProduct.setPrefWidth(320.0);
colSaleQuantity.setPrefWidth(70.0);
colSaleUnitPrice.setPrefWidth(115.0);
colSaleTotal.setPrefWidth(120.0);
colSalePaymentType.setPrefWidth(110.0);
return;
}
double extra = available - baseWidth;
colSaleId.setPrefWidth(60.0);
colSaleDate.setPrefWidth(170.0 + extra * 0.18);
colEmployeeName.setPrefWidth(160.0 + extra * 0.18);
colServiceProduct.setPrefWidth(320.0 + extra * 0.42);
colSaleQuantity.setPrefWidth(70.0);
colSaleUnitPrice.setPrefWidth(115.0 + extra * 0.08);
colSaleTotal.setPrefWidth(120.0 + extra * 0.08);
colSalePaymentType.setPrefWidth(110.0 + extra * 0.06);
}
private void updateCartColumnWidths(double tableWidth) {
double available = Math.max(tableWidth - 28.0, 0.0);
double baseWidth = 640.0;
if (available <= 0) {
return;
}
if (available <= baseWidth) {
colCartProduct.setPrefWidth(310.0);
colCartQty.setPrefWidth(90.0);
colCartUnitPrice.setPrefWidth(120.0);
colCartTotal.setPrefWidth(120.0);
return;
}
double extra = available - baseWidth;
colCartProduct.setPrefWidth(310.0 + extra * 0.55);
colCartQty.setPrefWidth(90.0);
colCartUnitPrice.setPrefWidth(120.0 + extra * 0.2);
colCartTotal.setPrefWidth(120.0 + extra * 0.25);
}
private void setCreateSaleControlsDisabled(boolean disabled) {
cbProduct.setDisable(disabled);
spQuantity.setDisable(disabled);

View File

@@ -10,171 +10,185 @@
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<ScrollPane fitToHeight="true" fitToWidth="false" hbarPolicy="AS_NEEDED" vbarPolicy="AS_NEEDED" pannable="true" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.SaleController">
<ScrollPane fitToHeight="true" fitToWidth="true" hbarPolicy="AS_NEEDED" vbarPolicy="AS_NEEDED" pannable="true" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.SaleController">
<content>
<VBox minHeight="-Infinity" minWidth="-Infinity" prefWidth="1100.0" spacing="6.0" style="-fx-font-size: 14px;">
<padding>
<Insets bottom="6.0" left="6.0" right="6.0" top="6.0" />
</padding>
<children>
<HBox alignment="CENTER_LEFT" prefHeight="50.0" spacing="8.0">
<children>
<Label text="Sales" textFill="#2c3e50">
<font>
<Font name="System Bold" size="20.0" />
</font>
<HBox.margin>
<Insets />
</HBox.margin>
</Label>
<Label fx:id="lblModeNote" text="" textFill="#7f8c8d">
<font>
<Font name="System Bold" size="11.0" />
</font>
<padding>
<Insets top="4.0" />
</padding>
</Label>
<Label fx:id="lblStatus" text="" textFill="#16a085" visible="false" managed="true">
<font>
<Font name="System Bold" size="11.0" />
</font>
<padding>
<Insets right="8.0" />
</padding>
</Label>
<Region HBox.hgrow="ALWAYS" />
<Button fx:id="btnRefund" mnemonicParsing="false" onAction="#btnRefund" prefHeight="32.0" style="-fx-background-color: #FF6b6b; -fx-cursor: hand; -fx-background-radius: 8;" text="Process Refund" 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="#btnRefresh" prefHeight="32.0" prefWidth="96.0" style="-fx-background-color: #4ECDC4; -fx-cursor: hand; -fx-background-radius: 8;" text="Refresh" 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>
</children>
</HBox>
<VBox fx:id="vbCreateSale" spacing="2.0" style="-fx-background-color: #ffffff; -fx-background-radius: 12; -fx-border-color: #e6e6e6; -fx-border-radius: 12; -fx-border-width: 1;">
<padding>
<Insets bottom="4.0" left="4.0" right="4.0" top="4.0" />
</padding>
<children>
<Label text="Create Sale" textFill="#2c3e50">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<HBox alignment="CENTER_LEFT" spacing="6.0">
<children>
<ComboBox fx:id="cbProduct" prefHeight="24.0" prefWidth="240.0" promptText="Select a product" />
<Spinner fx:id="spQuantity" prefHeight="24.0" prefWidth="70.0" />
<Button fx:id="btnAddToCart" mnemonicParsing="false" onAction="#btnAddToCart" prefHeight="24.0" style="-fx-background-color: #FF6b6b; -fx-cursor: hand; -fx-background-radius: 8;" text="Add" textFill="WHITE">
<font>
<Font name="System Bold" size="13.0" />
</font>
<padding>
<Insets bottom="8.0" left="18.0" right="18.0" top="8.0" />
</padding>
</Button>
<Button fx:id="btnRemoveSelected" mnemonicParsing="false" onAction="#btnRemoveSelected" prefHeight="24.0" style="-fx-background-color: #34495E; -fx-cursor: hand; -fx-background-radius: 8;" text="Remove Selected" textFill="WHITE">
<font>
<Font name="System Bold" size="13.0" />
</font>
<padding>
<Insets bottom="8.0" left="18.0" right="18.0" top="8.0" />
</padding>
</Button>
</children>
</HBox>
<TableView fx:id="tvCart" prefHeight="72.0" style="-fx-background-color: white; -fx-background-radius: 10;" VBox.vgrow="NEVER">
<columns>
<TableColumn fx:id="colCartProduct" prefWidth="310.0" text="Product" />
<TableColumn fx:id="colCartQty" prefWidth="90.0" text="Qty" />
<TableColumn fx:id="colCartUnitPrice" prefWidth="120.0" text="Unit Price" />
<TableColumn fx:id="colCartTotal" prefWidth="120.0" text="Total" />
</columns>
</TableView>
<Separator />
<HBox alignment="CENTER_LEFT" spacing="12.0">
<children>
<Label text="Payment" textFill="#2c3e50">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<ComboBox fx:id="cbPaymentMethod" prefHeight="34.0" prefWidth="160.0" />
<Region HBox.hgrow="ALWAYS" />
<Label text="Total:" textFill="#2c3e50">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<Label fx:id="lblCartTotal" text="\$0.00" textFill="#2c3e50">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
<Region prefWidth="20.0" />
<Button fx:id="btnClearCart" mnemonicParsing="false" onAction="#btnClearCart" prefHeight="36.0" style="-fx-background-color: transparent; -fx-border-color: #FF6b6b; -fx-border-radius: 8; -fx-cursor: hand;" text="Clear" textFill="#FF6b6b">
<font>
<Font name="System Bold" size="13.0" />
</font>
<padding>
<Insets bottom="8.0" left="18.0" right="18.0" top="8.0" />
</padding>
</Button>
<Button fx:id="btnSaveSale" mnemonicParsing="false" onAction="#btnSaveSale" prefHeight="36.0" style="-fx-background-color: #4ECDC4; -fx-cursor: hand; -fx-background-radius: 8;" text="Save Sale" textFill="WHITE">
<font>
<Font name="System Bold" size="13.0" />
</font>
<padding>
<Insets bottom="8.0" left="18.0" right="18.0" top="8.0" />
</padding>
</Button>
</children>
</HBox>
</children>
</VBox>
<HBox alignment="CENTER_LEFT" prefHeight="24.0" spacing="10.0" style="-fx-background-color: white; -fx-background-radius: 14; -fx-border-width: 1; -fx-border-radius: 14; -fx-border-color: #e6e6e6;">
<VBox minHeight="-Infinity" minWidth="0.0" maxWidth="Infinity" spacing="10.0" style="-fx-font-size: 14px;">
<padding>
<Insets bottom="10.0" left="15.0" right="15.0" top="10.0" />
<Insets bottom="16.0" left="16.0" right="16.0" top="16.0" />
</padding>
<children>
<TextField fx:id="txtSearch" prefHeight="22.0" prefWidth="150.0" promptText="Search sales..." style="-fx-border-width: 0; -fx-background-color: transparent;" HBox.hgrow="ALWAYS">
<font>
<Font size="15.0" />
</font>
</TextField>
<HBox alignment="CENTER_LEFT" spacing="12.0" maxWidth="Infinity">
<children>
<VBox spacing="2.0" HBox.hgrow="ALWAYS">
<children>
<Label text="Sales" textFill="#2c3e50">
<font>
<Font name="System Bold" size="20.0" />
</font>
</Label>
<HBox spacing="8.0">
<children>
<Label fx:id="lblModeNote" text="" textFill="#7f8c8d">
<font>
<Font name="System Bold" size="11.0" />
</font>
</Label>
<Label fx:id="lblStatus" text="" textFill="#16a085" visible="false" managed="true">
<font>
<Font name="System Bold" size="11.0" />
</font>
</Label>
</children>
</HBox>
</children>
</VBox>
<FlowPane hgap="8.0" maxWidth="Infinity" prefWrapLength="260.0" vgap="8.0">
<children>
<Button fx:id="btnRefund" mnemonicParsing="false" onAction="#btnRefund" prefHeight="32.0" style="-fx-background-color: #FF6b6b; -fx-cursor: hand; -fx-background-radius: 8;" text="Process Refund" 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="#btnRefresh" prefHeight="32.0" prefWidth="96.0" style="-fx-background-color: #4ECDC4; -fx-cursor: hand; -fx-background-radius: 8;" text="Refresh" 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>
</children>
</FlowPane>
</children>
</HBox>
<VBox fx:id="vbCreateSale" maxWidth="Infinity" spacing="10.0" style="-fx-background-color: #ffffff; -fx-background-radius: 12; -fx-border-color: #e6e6e6; -fx-border-radius: 12; -fx-border-width: 1;">
<padding>
<Insets bottom="12.0" left="12.0" right="12.0" top="12.0" />
</padding>
<children>
<Label text="Create Sale" textFill="#2c3e50">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<FlowPane hgap="8.0" maxWidth="Infinity" prefWrapLength="680.0" vgap="8.0">
<children>
<ComboBox fx:id="cbProduct" minWidth="220.0" prefHeight="24.0" prefWidth="320.0" promptText="Select a product" />
<Spinner fx:id="spQuantity" prefHeight="24.0" prefWidth="90.0" />
<Button fx:id="btnAddToCart" mnemonicParsing="false" onAction="#btnAddToCart" prefHeight="24.0" style="-fx-background-color: #FF6b6b; -fx-cursor: hand; -fx-background-radius: 8;" text="Add" textFill="WHITE">
<font>
<Font name="System Bold" size="13.0" />
</font>
<padding>
<Insets bottom="8.0" left="18.0" right="18.0" top="8.0" />
</padding>
</Button>
<Button fx:id="btnRemoveSelected" mnemonicParsing="false" onAction="#btnRemoveSelected" prefHeight="24.0" style="-fx-background-color: #34495E; -fx-cursor: hand; -fx-background-radius: 8;" text="Remove Selected" textFill="WHITE">
<font>
<Font name="System Bold" size="13.0" />
</font>
<padding>
<Insets bottom="8.0" left="18.0" right="18.0" top="8.0" />
</padding>
</Button>
</children>
</FlowPane>
<TableView fx:id="tvCart" prefHeight="120.0" style="-fx-background-color: white; -fx-background-radius: 10;" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="colCartProduct" prefWidth="310.0" text="Product" />
<TableColumn fx:id="colCartQty" prefWidth="90.0" text="Qty" />
<TableColumn fx:id="colCartUnitPrice" prefWidth="120.0" text="Unit Price" />
<TableColumn fx:id="colCartTotal" prefWidth="120.0" text="Total" />
</columns>
</TableView>
<Separator />
<HBox alignment="CENTER_LEFT" spacing="12.0" maxWidth="Infinity">
<children>
<HBox alignment="CENTER_LEFT" spacing="8.0">
<children>
<Label text="Payment" textFill="#2c3e50">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<ComboBox fx:id="cbPaymentMethod" prefHeight="34.0" prefWidth="160.0" />
</children>
</HBox>
<Region HBox.hgrow="ALWAYS" />
<HBox alignment="CENTER_LEFT" spacing="8.0">
<children>
<Label text="Total:" textFill="#2c3e50">
<font>
<Font name="System Bold" size="13.0" />
</font>
</Label>
<Label fx:id="lblCartTotal" text="\$0.00" textFill="#2c3e50">
<font>
<Font name="System Bold" size="16.0" />
</font>
</Label>
</children>
</HBox>
<FlowPane hgap="8.0" prefWrapLength="220.0" vgap="8.0">
<children>
<Button fx:id="btnClearCart" mnemonicParsing="false" onAction="#btnClearCart" prefHeight="36.0" style="-fx-background-color: transparent; -fx-border-color: #FF6b6b; -fx-border-radius: 8; -fx-cursor: hand;" text="Clear" textFill="#FF6b6b">
<font>
<Font name="System Bold" size="13.0" />
</font>
<padding>
<Insets bottom="8.0" left="18.0" right="18.0" top="8.0" />
</padding>
</Button>
<Button fx:id="btnSaveSale" mnemonicParsing="false" onAction="#btnSaveSale" prefHeight="36.0" style="-fx-background-color: #4ECDC4; -fx-cursor: hand; -fx-background-radius: 8;" text="Save Sale" textFill="WHITE">
<font>
<Font name="System Bold" size="13.0" />
</font>
<padding>
<Insets bottom="8.0" left="18.0" right="18.0" top="8.0" />
</padding>
</Button>
</children>
</FlowPane>
</children>
</HBox>
</children>
</VBox>
<HBox alignment="CENTER_LEFT" prefHeight="24.0" spacing="10.0" style="-fx-background-color: white; -fx-background-radius: 14; -fx-border-width: 1; -fx-border-radius: 14; -fx-border-color: #e6e6e6;" maxWidth="Infinity">
<padding>
<Insets bottom="10.0" left="15.0" right="15.0" top="10.0" />
</padding>
<children>
<TextField fx:id="txtSearch" prefHeight="22.0" promptText="Search sales..." style="-fx-border-width: 0; -fx-background-color: transparent;" HBox.hgrow="ALWAYS">
<font>
<Font size="15.0" />
</font>
</TextField>
</children>
</HBox>
<TableView fx:id="tvSales" prefHeight="270.0" style="-fx-background-color: white; -fx-background-radius: 12; -fx-padding: 2;" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="colSaleId" minWidth="50.0" prefWidth="60.0" text="ID" />
<TableColumn fx:id="colSaleDate" minWidth="150.0" prefWidth="170.0" text="Date" />
<TableColumn fx:id="colEmployeeName" minWidth="150.0" prefWidth="160.0" text="Employee" />
<TableColumn fx:id="colServiceProduct" minWidth="260.0" prefWidth="320.0" text="Product" />
<TableColumn fx:id="colSaleQuantity" minWidth="55.0" prefWidth="70.0" text="Qty" />
<TableColumn fx:id="colSaleUnitPrice" minWidth="100.0" prefWidth="115.0" text="Unit Price" />
<TableColumn fx:id="colSaleTotal" minWidth="100.0" prefWidth="120.0" text="Total" />
<TableColumn fx:id="colSalePaymentType" minWidth="95.0" prefWidth="110.0" text="Payment" />
</columns>
</TableView>
</children>
</HBox>
<TableView fx:id="tvSales" prefHeight="270.0" prefWidth="1180.0" style="-fx-background-color: white; -fx-background-radius: 12; -fx-padding: 2;" VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="colSaleId" minWidth="50.0" prefWidth="60.0" text="ID" />
<TableColumn fx:id="colSaleDate" minWidth="150.0" prefWidth="170.0" text="Date" />
<TableColumn fx:id="colEmployeeName" minWidth="150.0" prefWidth="160.0" text="Employee" />
<TableColumn fx:id="colServiceProduct" minWidth="260.0" prefWidth="320.0" text="Product" />
<TableColumn fx:id="colSaleQuantity" minWidth="55.0" prefWidth="70.0" text="Qty" />
<TableColumn fx:id="colSaleUnitPrice" minWidth="100.0" prefWidth="115.0" text="Unit Price" />
<TableColumn fx:id="colSaleTotal" minWidth="100.0" prefWidth="120.0" text="Total" />
<TableColumn fx:id="colSalePaymentType" minWidth="95.0" prefWidth="110.0" text="Payment" />
</columns>
</TableView>
</children>
</VBox>
</content>
</ScrollPane>