Added CRUD to Products and added Validation to dialog
This commit is contained in:
@@ -11,17 +11,15 @@ import org.example.petshopdesktop.models.Product;
|
||||
public class ProductDTO {
|
||||
private SimpleIntegerProperty prodId;
|
||||
private SimpleStringProperty prodName;
|
||||
private SimpleStringProperty prodSku;
|
||||
private SimpleDoubleProperty prodPrice;
|
||||
private SimpleIntegerProperty categoryId; //used for edit and delete
|
||||
private SimpleStringProperty categoryName;
|
||||
private SimpleStringProperty prodDesc;
|
||||
|
||||
//constructor
|
||||
public ProductDTO(int prodId, String prodName, String prodSku, double prodPrice, int categoryId, String categoryName, String prodDesc) {
|
||||
public ProductDTO(int prodId, String prodName, double prodPrice, int categoryId, String categoryName, String prodDesc) {
|
||||
this.prodId = new SimpleIntegerProperty(prodId);
|
||||
this.prodName = new SimpleStringProperty(prodName);
|
||||
this.prodSku = new SimpleStringProperty(prodSku);
|
||||
this.prodPrice = new SimpleDoubleProperty(prodPrice);
|
||||
this.categoryId = new SimpleIntegerProperty(categoryId);
|
||||
this.categoryName = new SimpleStringProperty(categoryName);
|
||||
@@ -53,18 +51,6 @@ public class ProductDTO {
|
||||
this.prodName.set(prodName);
|
||||
}
|
||||
|
||||
public String getProdSku() {
|
||||
return prodSku.get();
|
||||
}
|
||||
|
||||
public SimpleStringProperty prodSkuProperty() {
|
||||
return prodSku;
|
||||
}
|
||||
|
||||
public void setProdSku(String prodSku) {
|
||||
this.prodSku.set(prodSku);
|
||||
}
|
||||
|
||||
public double getProdPrice() {
|
||||
return prodPrice.get();
|
||||
}
|
||||
@@ -121,7 +107,6 @@ public class ProductDTO {
|
||||
Product product = new Product(
|
||||
getProdId(),
|
||||
getProdName(),
|
||||
getProdSku(),
|
||||
getProdPrice(),
|
||||
getCategoryId(),
|
||||
getProdDesc()
|
||||
|
||||
131
src/main/java/org/example/petshopdesktop/Validator.java
Normal file
131
src/main/java/org/example/petshopdesktop/Validator.java
Normal file
@@ -0,0 +1,131 @@
|
||||
package org.example.petshopdesktop;
|
||||
|
||||
public class Validator {
|
||||
|
||||
/**
|
||||
* Checks if string is not empty
|
||||
* @param value string to check
|
||||
* @param name name of the input
|
||||
* @return error msg if string is not empty, otherwise empty
|
||||
*/
|
||||
public static String isPresent(String value, String name){
|
||||
String msg =""; //OK so far
|
||||
if(value.isEmpty() || name.isBlank()){
|
||||
msg += name + " is required. \n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the input is a non-negative double
|
||||
* @param value input of string
|
||||
* @param name name of input
|
||||
* @return error msg if input is not a number or negative, otherwise empty
|
||||
*/
|
||||
public static String isNonNegativeDouble(String value, String name){
|
||||
String msg =""; //OK so far
|
||||
double result;
|
||||
try{
|
||||
result = Double.parseDouble(value);
|
||||
if (result < 0){
|
||||
msg += name + " must be greater than or equal 0. \n";
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e){
|
||||
msg += name + " must be a number.\n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the input is a double in 2 different range
|
||||
* @param value input of string
|
||||
* @param name name of inpt
|
||||
* @param minValue min value of range
|
||||
* @param maxValue max value of range
|
||||
* @return error msg if input is out of range, otherwise empty
|
||||
*/
|
||||
public static String isDoubleInRange(String value, String name, double minValue, double maxValue){
|
||||
String msg =""; //OK so far
|
||||
double result;
|
||||
try{
|
||||
result = Double.parseDouble(value);
|
||||
if (result < minValue || result > maxValue){
|
||||
msg += name + " must be between " + minValue + " and " + maxValue + "\n";
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e){
|
||||
msg += name + " must be a number.\n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the input is a non-negative integer
|
||||
* @param value input of string
|
||||
* @param name name of input
|
||||
* @return error msg if input is not a number or negative, otherwise empty
|
||||
*/
|
||||
public static String isNonNegativeInteger(String value, String name){
|
||||
String msg =""; //OK so far
|
||||
int result;
|
||||
try{
|
||||
result = Integer.parseInt(value);
|
||||
if (result < 0){
|
||||
msg += name + " must be greater than or equal 0. \n";
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e){
|
||||
msg += name + " must be a whole number.\n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the string is a given amount of characters or fewer
|
||||
* @param value input of string
|
||||
* @param name name of input
|
||||
* @return error msg if input is more than given characters length
|
||||
*/
|
||||
public static String isLessThanVarChars(String value, String name, int length){
|
||||
String msg ="";
|
||||
if (value.length() > length){
|
||||
msg += name + " must be less than " + length + " characters. \n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the input is a valid email format
|
||||
* @param value input of string
|
||||
* @param name name of input
|
||||
* @return error msg if input is not a valid email format, otherwise empty
|
||||
*/
|
||||
public static String isValidEmail(String value, String name){
|
||||
String msg = ""; //OK so far
|
||||
// Email regex
|
||||
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
|
||||
|
||||
if (!value.matches(regex)){
|
||||
msg += name + " is not in a valid format. \n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the input is a valid phone number in format XXX-XXX-XXXX
|
||||
* @param value input of string
|
||||
* @param name name of input
|
||||
* @return error msg if input is not in valid phone format, otherwise empty
|
||||
*/
|
||||
public static String isValidPhoneNumber(String value, String name){
|
||||
String msg = ""; //OK so far
|
||||
// Phone regex
|
||||
String regex = "^\\d{3}-\\d{3}-\\d{4}$";
|
||||
|
||||
if (!value.matches(regex)){
|
||||
msg += name + " must be in format XXX-XXX-XXXX. \n";
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
@@ -4,16 +4,24 @@ import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.DTOs.ProductDTO;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.ProductDialogController;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController;
|
||||
import org.example.petshopdesktop.database.ProductDB;
|
||||
import org.example.petshopdesktop.database.SupplierDB;
|
||||
import org.example.petshopdesktop.models.Product;
|
||||
import org.example.petshopdesktop.models.Supplier;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLIntegrityConstraintViolationException;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* The controller for any operations in the products view
|
||||
@@ -44,9 +52,6 @@ public class ProductController {
|
||||
@FXML
|
||||
private TableColumn<ProductDTO, Double> colProductPrice;
|
||||
|
||||
@FXML
|
||||
private TableColumn<ProductDTO, String> colProductSKU;
|
||||
|
||||
@FXML
|
||||
private TableView<ProductDTO> tvProducts;
|
||||
|
||||
@@ -68,19 +73,31 @@ public class ProductController {
|
||||
//set up table columns
|
||||
colProductId.setCellValueFactory(new PropertyValueFactory<ProductDTO,Integer>("prodId"));
|
||||
colProductName.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodName"));
|
||||
colProductSKU.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodSku"));
|
||||
colProductPrice.setCellValueFactory(new PropertyValueFactory<ProductDTO,Double>("prodPrice"));
|
||||
colProductCategory.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("categoryName"));
|
||||
colProductDesc.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodDesc"));
|
||||
|
||||
displayProducts();
|
||||
displayProduct();
|
||||
|
||||
//EventListener to Enable buttons when a row is selected
|
||||
tvProducts.getSelectionModel().selectedItemProperty().addListener(
|
||||
(observable, oldValue, newValue) -> {
|
||||
btnEdit.setDisable(false);
|
||||
btnDelete.setDisable(false);
|
||||
}
|
||||
);
|
||||
|
||||
//EventListener to search when text is changed on searchbar
|
||||
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
displayFilteredProduct(newValue);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the productDTO to table view
|
||||
*/
|
||||
private void displayProducts(){
|
||||
private void displayProduct(){
|
||||
//Erase old content
|
||||
data.clear();
|
||||
|
||||
@@ -95,20 +112,148 @@ public class ProductController {
|
||||
tvProducts.setItems(data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* open a new dialog for adding a product
|
||||
* @param event
|
||||
*/
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
|
||||
mode = "Add";
|
||||
openDialog(null,mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a selected product when delete is clicked
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnDeleteClicked(ActionEvent event) {
|
||||
int numRows = 0;
|
||||
//set selected product
|
||||
ProductDTO selectedProduct = tvProducts.getSelectionModel().getSelectedItem();
|
||||
|
||||
//ask user to confirm
|
||||
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
question.setHeaderText("Please confirm delete");
|
||||
question.setContentText("Are you sure you want to delete this product?");
|
||||
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
||||
|
||||
//if confirmed,start deletion
|
||||
if (result.isPresent() && result.get() == ButtonType.OK) {
|
||||
int prodId = selectedProduct.getProdId();
|
||||
|
||||
//try deleting
|
||||
try{
|
||||
numRows = ProductDB.deleteProduct(prodId);
|
||||
}
|
||||
catch (SQLIntegrityConstraintViolationException e){
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setHeaderText("Database Operation Error");
|
||||
alert.setContentText("Delete failed\n" +
|
||||
"the selected product is being referred in another table");
|
||||
alert.showAndWait();
|
||||
return;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
//prompt user of any errors
|
||||
if (numRows == 0){
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setHeaderText("Database Operation Error");
|
||||
alert.setContentText("Delete failed");
|
||||
alert.showAndWait();
|
||||
}
|
||||
else{
|
||||
//prompt user of delete conformation
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.setHeaderText("Database Operation Confirmed");
|
||||
alert.setContentText("Delete successful");
|
||||
alert.showAndWait();
|
||||
//refresh display and reset inputs
|
||||
displayProduct();
|
||||
btnDelete.setDisable(true);
|
||||
btnEdit.setDisable(true);
|
||||
txtSearch.setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a new dialog for editing a product
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnEditClicked(ActionEvent event) {
|
||||
//set selected product
|
||||
ProductDTO selectedProduct = tvProducts.getSelectionModel().getSelectedItem();
|
||||
|
||||
if (selectedProduct != null) {
|
||||
mode = "Edit";
|
||||
openDialog(selectedProduct, mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the table given the string from the searchbar
|
||||
* @param filter word to filter table
|
||||
*/
|
||||
private void displayFilteredProduct(String filter){
|
||||
data.clear();
|
||||
try{
|
||||
if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){
|
||||
displayProduct(); //If search bar is empty just display everything
|
||||
}
|
||||
else{
|
||||
//Filter the using the keyword
|
||||
data = ProductDB.getFilteredProductDTOs(filter);
|
||||
tvProducts.setItems(data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to open the new Dialog for edit or adding
|
||||
* depending on the mode given
|
||||
* @param product the product entity for editing, null if adding
|
||||
* @param mode the mode the dialog should be in
|
||||
*/
|
||||
private void openDialog(ProductDTO product, String mode){
|
||||
//Get new view
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/product-dialog-view.fxml"));
|
||||
Scene scene = null;
|
||||
try{
|
||||
scene = new Scene(fxmlLoader.load());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
ProductDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
||||
dialogController.setMode(mode);
|
||||
|
||||
//Open the dialog depending on the mode
|
||||
if(mode.equals("Edit")){
|
||||
//Make it display suppliers details in dialog
|
||||
dialogController.displayProductDetails(product);
|
||||
}
|
||||
Stage dialogStage = new Stage();
|
||||
dialogStage.initModality(Modality.APPLICATION_MODAL); //make it modal
|
||||
if(mode.equals("Add")){
|
||||
dialogStage.setTitle("Add Product");
|
||||
}
|
||||
else {
|
||||
dialogStage.setTitle("Edit Product");
|
||||
}
|
||||
dialogStage.setScene(scene);
|
||||
dialogStage.showAndWait();
|
||||
|
||||
//When dialog closes update table view and disable edit and delete buttons, and reset search bar
|
||||
displayProduct();
|
||||
btnDelete.setDisable(true);
|
||||
btnEdit.setDisable(true);
|
||||
txtSearch.setText("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class SupplierController {
|
||||
|
||||
displaySupplier();
|
||||
|
||||
// Enable buttons when a row is selected
|
||||
//EventListener to Enable buttons when a row is selected
|
||||
tvSuppliers.getSelectionModel().selectedItemProperty().addListener(
|
||||
(observable, oldValue, newValue) -> {
|
||||
btnEdit.setDisable(false);
|
||||
@@ -82,6 +82,11 @@ public class SupplierController {
|
||||
}
|
||||
);
|
||||
|
||||
//EventListener to search when text is changed on searchbar
|
||||
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
displayFilteredSupplier(newValue);
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -100,10 +105,30 @@ public class SupplierController {
|
||||
tvSuppliers.setItems(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the table given the string from the searchbar
|
||||
* @param filter word to filter table
|
||||
*/
|
||||
private void displayFilteredSupplier(String filter){
|
||||
data.clear();
|
||||
try{
|
||||
if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){
|
||||
displaySupplier(); //If search bar is empty just display everything
|
||||
}
|
||||
else{
|
||||
//Filter the using the keyword
|
||||
data = SupplierDB.getFilteredSuppliers(filter);
|
||||
tvSuppliers.setItems(data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* open a new dialog for adding a supplier
|
||||
* @param event
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
@@ -112,8 +137,8 @@ public class SupplierController {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param event
|
||||
* Delete a selected supplier when delete is clicked
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnDeleteClicked(ActionEvent event) {
|
||||
@@ -162,13 +187,16 @@ public class SupplierController {
|
||||
alert.showAndWait();
|
||||
//refresh display
|
||||
displaySupplier();
|
||||
btnDelete.setDisable(true);
|
||||
btnEdit.setDisable(true);
|
||||
txtSearch.setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a new dialog for editing a supplier
|
||||
* @param event click event
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnEditClicked(ActionEvent event) {
|
||||
@@ -184,12 +212,12 @@ public class SupplierController {
|
||||
/**
|
||||
* Function to open the new Dialog for edit or adding
|
||||
* depending on the mode given
|
||||
* @param supplier the supplier entity fo editing, null if adding
|
||||
* @param supplier the supplier entity for editing, null if adding
|
||||
* @param mode the mode the dialog should be in
|
||||
*/
|
||||
private void openDialog(Supplier supplier, String mode){
|
||||
//Get new view
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/supplier-dialog-view.fxml")); //CHECK
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/supplier-dialog-view.fxml"));
|
||||
Scene scene = null;
|
||||
try{
|
||||
scene = new Scene(fxmlLoader.load());
|
||||
@@ -215,10 +243,11 @@ public class SupplierController {
|
||||
dialogStage.setScene(scene);
|
||||
dialogStage.showAndWait();
|
||||
|
||||
//When dialog closes update table view and disable edit and delete buttons
|
||||
//When dialog closes update table view and disable edit and delete buttons, and reset search bar
|
||||
displaySupplier();
|
||||
btnDelete.setDisable(true);
|
||||
btnEdit.setDisable(true);
|
||||
txtSearch.setText("");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
package org.example.petshopdesktop.controllers.dialogcontrollers;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.DTOs.ProductDTO;
|
||||
import org.example.petshopdesktop.Validator;
|
||||
import org.example.petshopdesktop.database.CategoryDB;
|
||||
import org.example.petshopdesktop.database.ProductDB;
|
||||
import org.example.petshopdesktop.models.Category;
|
||||
import org.example.petshopdesktop.models.Product;
|
||||
import org.example.petshopdesktop.models.Supplier;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class ProductDialogController {
|
||||
|
||||
@FXML
|
||||
private Button btnCancel;
|
||||
|
||||
@FXML
|
||||
private Button btnSave;
|
||||
|
||||
@FXML
|
||||
private ComboBox<Category> cbProdCategory;
|
||||
|
||||
@FXML
|
||||
private Label lblMode;
|
||||
|
||||
@FXML
|
||||
private Label lblProdId;
|
||||
|
||||
@FXML
|
||||
private TextField txtProdDesc;
|
||||
|
||||
@FXML
|
||||
private TextField txtProdName;
|
||||
|
||||
@FXML
|
||||
private TextField txtProdPrice;
|
||||
|
||||
private String mode = null;
|
||||
|
||||
/**
|
||||
* Add event listeners to buttons when dialog loads
|
||||
*/
|
||||
@FXML
|
||||
void initialize() {
|
||||
//Set up mouse handlers for buttons
|
||||
btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent mouseEvent) {
|
||||
buttonSaveClicked(mouseEvent);
|
||||
}
|
||||
});
|
||||
|
||||
btnCancel.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent mouseEvent) {
|
||||
closeStage(mouseEvent);
|
||||
}
|
||||
});
|
||||
|
||||
//Set up combobox for selecting category
|
||||
try {
|
||||
//set up combobox
|
||||
ObservableList<Category> categories = FXCollections.observableArrayList(); //empty list
|
||||
categories = CategoryDB.getCategories();
|
||||
cbProdCategory.setItems(categories);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void buttonSaveClicked(MouseEvent mouseEvent) {
|
||||
int numRow = 0; //how many rows affected
|
||||
String errorMsg = ""; //error message for validation
|
||||
|
||||
//Check Validation (input required)
|
||||
errorMsg += Validator.isPresent(txtProdName.getText(), "Product Name");
|
||||
errorMsg += Validator.isPresent(txtProdPrice.getText(), "Product Price");
|
||||
if (cbProdCategory.getSelectionModel().getSelectedItem() == null) {
|
||||
errorMsg += "Category is required \n";
|
||||
}
|
||||
|
||||
//Check validation (length size)
|
||||
errorMsg += Validator.isLessThanVarChars(txtProdName.getText(), "Product Name", 100);
|
||||
errorMsg += Validator.isLessThanVarChars(txtProdDesc.getText(), "Description", 100);
|
||||
errorMsg += Validator.isLessThanVarChars(txtProdPrice.getText(), "Product Price", 12);
|
||||
|
||||
//Check Validation (format)
|
||||
errorMsg += Validator.isNonNegativeDouble(txtProdPrice.getText(), "Product Price");
|
||||
|
||||
if (errorMsg.isEmpty()) { //no validation errors detected
|
||||
Product product = collectProduct(); //get product info
|
||||
if (mode.equals("Add")){ //add mode
|
||||
try{
|
||||
numRow = ProductDB.insertProduct(product);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else { //edit
|
||||
try{
|
||||
numRow = ProductDB.updateProduct(product.getProdId(),product);
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
//if no rows were affected then there was an error (prompt user of error)
|
||||
if (numRow == 0){
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setHeaderText("Database Operation Error");
|
||||
alert.setContentText(mode + " failed");
|
||||
alert.showAndWait();
|
||||
closeStage(mouseEvent);
|
||||
}
|
||||
else {
|
||||
//tell the user operation was successful
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.setHeaderText("Database Operation Confirmed");
|
||||
alert.setContentText(mode + " succeeded");
|
||||
alert.showAndWait();
|
||||
closeStage(mouseEvent);
|
||||
}
|
||||
}
|
||||
else{ //Display validation errors
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setHeaderText("Input Error");
|
||||
alert.setContentText(errorMsg);
|
||||
alert.showAndWait();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect the product info
|
||||
* @return product info with the id or the new product
|
||||
*/
|
||||
private Product collectProduct(){
|
||||
int prodId = 0;
|
||||
Product product = null;
|
||||
|
||||
if(lblProdId.isVisible()){ //Edit mode
|
||||
//get product id from lblId (split the string so we only get the int)
|
||||
prodId = Integer.parseInt(lblProdId.getText().split(": ")[1]);
|
||||
}
|
||||
product = new Product(
|
||||
prodId,
|
||||
txtProdName.getText(),
|
||||
Double.parseDouble(txtProdPrice.getText()),
|
||||
cbProdCategory.getSelectionModel().getSelectedItem().getCategoryId(),
|
||||
txtProdDesc.getText()
|
||||
);
|
||||
return product;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the product data in text fields and combobox
|
||||
* @param product the supplier entity containing data to display
|
||||
*/
|
||||
public void displayProductDetails(ProductDTO product){
|
||||
if (product!=null){
|
||||
lblProdId.setText("ID: " + product.getProdId());
|
||||
txtProdName.setText(product.getProdName());
|
||||
txtProdDesc.setText(product.getProdDesc());
|
||||
txtProdPrice.setText(product.getProdPrice() + "");
|
||||
|
||||
//get the right combobox selection
|
||||
for (Category category : cbProdCategory.getItems()) {
|
||||
if(category.getCategoryId() == product.getCategoryId()){
|
||||
cbProdCategory.setValue(category);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the window
|
||||
* @param mouseEvent mouse event to close
|
||||
*/
|
||||
private void closeStage(MouseEvent mouseEvent) {
|
||||
Node node = (Node) mouseEvent.getSource();
|
||||
Stage stage = (Stage) node.getScene().getWindow();
|
||||
stage.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode of the dialog
|
||||
* @param mode the mode to for the dialog
|
||||
*/
|
||||
public void setMode(String mode) {
|
||||
this.mode = mode;
|
||||
lblMode.setText(mode + " Product");
|
||||
if(mode.equals("Add")) {
|
||||
lblProdId.setVisible(false);
|
||||
}
|
||||
else if(mode.equals("Edit")) {
|
||||
lblProdId.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.Validator;
|
||||
import org.example.petshopdesktop.database.SupplierDB;
|
||||
import org.example.petshopdesktop.models.Supplier;
|
||||
|
||||
@@ -45,6 +46,9 @@ public class SupplierDialogController {
|
||||
|
||||
private String mode = null;
|
||||
|
||||
/**
|
||||
* Add event listeners to buttons when dialog loads
|
||||
*/
|
||||
@FXML
|
||||
void initialize() {
|
||||
//Set up mouse handlers for buttons
|
||||
@@ -67,7 +71,22 @@ public class SupplierDialogController {
|
||||
int numRow = 0; //how many rows affected
|
||||
String errorMsg = ""; //error message for validation
|
||||
|
||||
//TODO: Import validation class and validate text fields here
|
||||
//Check validation (input required)
|
||||
errorMsg += Validator.isPresent(txtCompanyName.getText(), "Company Name");
|
||||
errorMsg += Validator.isPresent(txtContactFirstName.getText(), "Contact First Name");
|
||||
errorMsg += Validator.isPresent(txtContactLastName.getText(), "Contact Last Name");
|
||||
errorMsg += Validator.isPresent(txtEmail.getText(), "Email Address");
|
||||
errorMsg += Validator.isPresent(txtPhone.getText(), "Phone Number");
|
||||
|
||||
//Check validation (Length size)
|
||||
errorMsg += Validator.isLessThanVarChars(txtCompanyName.getText(),"Company Name", 100);
|
||||
errorMsg += Validator.isLessThanVarChars(txtContactFirstName.getText(), "Contact First Name", 50);
|
||||
errorMsg += Validator.isLessThanVarChars(txtContactLastName.getText(), "Contact Last Name", 50);
|
||||
errorMsg += Validator.isLessThanVarChars(txtEmail.getText(), "Email Address", 100);
|
||||
|
||||
//Check validation (format)
|
||||
errorMsg += Validator.isValidEmail(txtEmail.getText(), "Email Address");
|
||||
errorMsg += Validator.isValidPhoneNumber(txtPhone.getText(), "Phone Number");
|
||||
|
||||
if(errorMsg.isEmpty()){ //no validation errors detected
|
||||
Supplier supplier = collectSupplier(); //get supplier info
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.example.petshopdesktop.database;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.example.petshopdesktop.models.Category;
|
||||
import org.example.petshopdesktop.models.Product;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class CategoryDB {
|
||||
/**
|
||||
* gets all the category into an observable list
|
||||
* @return a list of all the category
|
||||
* @throws SQLException if failed to find categories in the database
|
||||
*/
|
||||
public static ObservableList<Category> getCategories() throws SQLException{
|
||||
//Connect to the database
|
||||
ObservableList<Category> categories = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
//Execute Query
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery("SELECT * FROM category");
|
||||
|
||||
//While there is still data add categories to the list
|
||||
while(rs.next()){
|
||||
Category category = new Category(
|
||||
rs.getInt(1),
|
||||
rs.getString(2),
|
||||
rs.getString(3));
|
||||
categories.add(category);
|
||||
}
|
||||
|
||||
//close connection and return categories
|
||||
conn.close();
|
||||
return categories;
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,9 @@ import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.example.petshopdesktop.DTOs.ProductDTO;
|
||||
import org.example.petshopdesktop.models.Product;
|
||||
import org.example.petshopdesktop.models.Supplier;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.sql.*;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A class containing all the methods relating to CRUD on Products table
|
||||
@@ -34,10 +32,9 @@ public class ProductDB {
|
||||
Product product = new Product(
|
||||
rs.getInt(1),
|
||||
rs.getString(2),
|
||||
rs.getString(3),
|
||||
rs.getDouble(4),
|
||||
rs.getInt(5),
|
||||
rs.getString(6));
|
||||
rs.getDouble(3),
|
||||
rs.getInt(4),
|
||||
rs.getString(5));
|
||||
products.add(product);
|
||||
}
|
||||
|
||||
@@ -58,7 +55,7 @@ public class ProductDB {
|
||||
|
||||
//Execute Query
|
||||
Statement stmt = conn.createStatement();
|
||||
String sql = "SELECT p.prodId, p.prodName, p.prodSku, p.prodPrice, p.categoryId, c.categoryName, p.prodDesc " +
|
||||
String sql = "SELECT p.prodId, p.prodName, p.prodPrice, p.categoryId, c.categoryName, p.prodDesc " +
|
||||
"FROM product p " +
|
||||
"LEFT JOIN category c ON p.categoryId = c.categoryId";
|
||||
ResultSet rs = stmt.executeQuery(sql);
|
||||
@@ -68,11 +65,10 @@ public class ProductDB {
|
||||
ProductDTO product = new ProductDTO(
|
||||
rs.getInt(1),
|
||||
rs.getString(2),
|
||||
rs.getString(3),
|
||||
rs.getDouble(4),
|
||||
rs.getInt(5),
|
||||
rs.getString(6),
|
||||
rs.getString(7));
|
||||
rs.getDouble(3),
|
||||
rs.getInt(4),
|
||||
rs.getString(5),
|
||||
rs.getString(6));
|
||||
products.add(product);
|
||||
}
|
||||
|
||||
@@ -80,4 +76,137 @@ public class ProductDB {
|
||||
conn.close();
|
||||
return products;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new product to the database
|
||||
* @param product product entity to be inserted
|
||||
* @return number of rows affected in the database
|
||||
* @throws SQLException if insertion failed
|
||||
*/
|
||||
public static int insertProduct(Product product) throws SQLException {
|
||||
int numRows = 0;
|
||||
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
String sql = "INSERT INTO product (prodId, prodName, prodPrice, categoryId, prodDesc)" +
|
||||
"VALUES (?, ?, ?, ?, ?)";
|
||||
|
||||
//These are the values from product to put into the query above
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, product.getProdId());
|
||||
stmt.setString(2, product.getProdName());
|
||||
stmt.setDouble(3, product.getProdPrice());
|
||||
stmt.setInt(4, product.getCategoryId());
|
||||
stmt.setString(5, product.getProdDesc());
|
||||
|
||||
//update the number of rows affected, return and close connection
|
||||
numRows = stmt.executeUpdate();
|
||||
conn.close();
|
||||
|
||||
return numRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update an existing product to the database
|
||||
* @param prodId id of product
|
||||
* @param product new product data
|
||||
* @return number of rows affected in the database
|
||||
* @throws SQLException if update failed
|
||||
*/
|
||||
public static int updateProduct(int prodId, Product product) throws SQLException {
|
||||
int numRows = 0;
|
||||
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
String sql = "UPDATE product SET " +
|
||||
" prodName = ?, " +
|
||||
" prodPrice = ?, " +
|
||||
" categoryId = ?, " +
|
||||
" prodDesc = ? " +
|
||||
" WHERE prodId = ?";
|
||||
|
||||
//update values to query
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setString(1, product.getProdName());
|
||||
stmt.setDouble(2, product.getProdPrice());
|
||||
stmt.setInt(3, product.getCategoryId());
|
||||
stmt.setString(4, product.getProdDesc());
|
||||
stmt.setInt(5, prodId);
|
||||
|
||||
//Update rows and close connection
|
||||
numRows = stmt.executeUpdate();
|
||||
conn.close();
|
||||
|
||||
return numRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a product from the database
|
||||
* @param prodId product id to be deleted
|
||||
* @return number of rows affected in the database
|
||||
* @throws SQLException if delete failed
|
||||
*/
|
||||
public static int deleteProduct(int prodId) throws SQLException {
|
||||
int numRows = 0;
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
String sql = "DELETE FROM product WHERE prodId = ?";
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
|
||||
stmt.setInt(1, prodId);
|
||||
|
||||
//close connection and update rows affected
|
||||
numRows = stmt.executeUpdate();
|
||||
conn.close();
|
||||
|
||||
return numRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of productDTOs that is filtered by a given string
|
||||
* @param filter the word to filter table
|
||||
* @return ObservableList of ProductDTOs with the filtered data
|
||||
* @throws SQLException if getting products failed
|
||||
*/
|
||||
public static ObservableList<ProductDTO> getFilteredProductDTOs(String filter) throws SQLException {
|
||||
//Connect to the database
|
||||
ObservableList<ProductDTO> products = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
//Get SQL query for filtered word
|
||||
String sql =
|
||||
"SELECT p.prodId, p.prodName, p.prodPrice, p.categoryId, c.categoryName, p.prodDesc" +
|
||||
" FROM product p" +
|
||||
" LEFT JOIN category c ON p.categoryId = c.categoryId" +
|
||||
" WHERE " +
|
||||
"prodName LIKE ? OR " +
|
||||
"prodPrice LIKE ? OR " +
|
||||
"categoryName LIKE ? OR " +
|
||||
"prodDesc LIKE ?";
|
||||
|
||||
//add % wildcard so the query can use LIKE to filter data
|
||||
String filteredString = "%" + filter + "%";
|
||||
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setString(1, filteredString);
|
||||
stmt.setString(2, filteredString);
|
||||
stmt.setString(3, filteredString);
|
||||
stmt.setString(4, filteredString);
|
||||
|
||||
//execute query
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
|
||||
//While there is still data add products to the list
|
||||
while(rs.next()){
|
||||
ProductDTO product = new ProductDTO(
|
||||
rs.getInt(1),
|
||||
rs.getString(2),
|
||||
rs.getDouble(3),
|
||||
rs.getInt(4),
|
||||
rs.getString(5),
|
||||
rs.getString(6));
|
||||
products.add(product);
|
||||
}
|
||||
|
||||
conn.close();
|
||||
return products;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class SupplierDB {
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery("SELECT * FROM supplier");
|
||||
|
||||
//While there is still data add products to the list
|
||||
//While there is still data add suppliers to the list
|
||||
while(rs.next()){
|
||||
Supplier supplier = new Supplier(
|
||||
rs.getInt(1),
|
||||
@@ -127,4 +127,54 @@ public class SupplierDB {
|
||||
|
||||
return numRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of Suppliers that is filtered by a given string
|
||||
* @param filter the word to filter table
|
||||
* @return ObservableList of suppliers with the filtered data
|
||||
* @throws SQLException if getting suppliers failed
|
||||
*/
|
||||
public static ObservableList<Supplier> getFilteredSuppliers(String filter) throws SQLException {
|
||||
//Connect to the database
|
||||
ObservableList<Supplier> suppliers = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
//Get SQL query for filtered word
|
||||
String sql =
|
||||
"SELECT * FROM supplier" +
|
||||
" WHERE " +
|
||||
"supCompany LIKE ? OR " +
|
||||
"supContactFirstName LIKE ? OR " +
|
||||
"supContactLastName LIKE ? OR " +
|
||||
"supEmail LIKE ? OR " +
|
||||
"supPhone LIKE ?";
|
||||
|
||||
//add % wildcard so the query can use LIKE to filter data
|
||||
String filteredString = "%" + filter + "%";
|
||||
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setString(1, filteredString);
|
||||
stmt.setString(2, filteredString);
|
||||
stmt.setString(3, filteredString);
|
||||
stmt.setString(4, filteredString);
|
||||
stmt.setString(5, filteredString);
|
||||
|
||||
//execute query
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
|
||||
//While there is still data add suppliers to the list
|
||||
while(rs.next()){
|
||||
Supplier supplier = new Supplier(
|
||||
rs.getInt(1),
|
||||
rs.getString(2),
|
||||
rs.getString(3),
|
||||
rs.getString(4),
|
||||
rs.getString(5),
|
||||
rs.getString(6));
|
||||
suppliers.add(supplier);
|
||||
}
|
||||
|
||||
conn.close();
|
||||
return suppliers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.example.petshopdesktop.models;
|
||||
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
|
||||
public class Category {
|
||||
private SimpleIntegerProperty categoryId;
|
||||
private SimpleStringProperty categoryName;
|
||||
private SimpleStringProperty categoryType;
|
||||
|
||||
//Constrctor
|
||||
public Category(int categoryId, String categoryName, String categoryType) {
|
||||
this.categoryId = new SimpleIntegerProperty(categoryId);
|
||||
this.categoryName = new SimpleStringProperty(categoryName);
|
||||
this.categoryType = new SimpleStringProperty(categoryType);
|
||||
}
|
||||
|
||||
//getters and setters
|
||||
public int getCategoryId() {
|
||||
return categoryId.get();
|
||||
}
|
||||
|
||||
public SimpleIntegerProperty categoryIdProperty() {
|
||||
return categoryId;
|
||||
}
|
||||
|
||||
public void setCategoryId(int categoryId) {
|
||||
this.categoryId.set(categoryId);
|
||||
}
|
||||
|
||||
public String getCategoryName() {
|
||||
return categoryName.get();
|
||||
}
|
||||
|
||||
public SimpleStringProperty categoryNameProperty() {
|
||||
return categoryName;
|
||||
}
|
||||
|
||||
public void setCategoryName(String categoryName) {
|
||||
this.categoryName.set(categoryName);
|
||||
}
|
||||
|
||||
public String getCategoryType() {
|
||||
return categoryType.get();
|
||||
}
|
||||
|
||||
public SimpleStringProperty categoryTypeProperty() {
|
||||
return categoryType;
|
||||
}
|
||||
|
||||
public void setCategoryType(String categoryType) {
|
||||
this.categoryType.set(categoryType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getCategoryName();
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,14 @@ import javafx.beans.property.SimpleStringProperty;
|
||||
public class Product {
|
||||
private SimpleIntegerProperty prodId;
|
||||
private SimpleStringProperty prodName;
|
||||
private SimpleStringProperty prodSku;
|
||||
private SimpleDoubleProperty prodPrice;
|
||||
private SimpleIntegerProperty categoryId;
|
||||
private SimpleStringProperty prodDesc;
|
||||
|
||||
//constructor
|
||||
public Product(int prodId, String prodName, String prodSku, double prodPrice, int categoryId, String prodDesc) {
|
||||
public Product(int prodId, String prodName, double prodPrice, int categoryId, String prodDesc) {
|
||||
this.prodId = new SimpleIntegerProperty(prodId);
|
||||
this.prodName = new SimpleStringProperty(prodName);
|
||||
this.prodSku = new SimpleStringProperty(prodSku);
|
||||
this.prodPrice = new SimpleDoubleProperty(prodPrice);
|
||||
this.categoryId = new SimpleIntegerProperty(categoryId);
|
||||
this.prodDesc = new SimpleStringProperty(prodDesc);
|
||||
@@ -50,18 +48,6 @@ public class Product {
|
||||
this.prodName.set(prodName);
|
||||
}
|
||||
|
||||
public String getProdSku() {
|
||||
return prodSku.get();
|
||||
}
|
||||
|
||||
public SimpleStringProperty prodSkuProperty() {
|
||||
return prodSku;
|
||||
}
|
||||
|
||||
public void setProdSku(String prodSku) {
|
||||
this.prodSku.set(prodSku);
|
||||
}
|
||||
|
||||
public double getProdPrice() {
|
||||
return prodPrice.get();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
|
||||
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" 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.dialogcontrollers.ProductDialogController">
|
||||
<children>
|
||||
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
|
||||
<children>
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="246.0">
|
||||
<children>
|
||||
<Label fx:id="lblMode" prefHeight="54.0" prefWidth="246.0" text="Mode Product" textFill="WHITE">
|
||||
<font>
|
||||
<Font name="Comic Sans MS Bold" size="30.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="lblProdId" text="ID: 1" textFill="#ffe66d">
|
||||
<font>
|
||||
<Font size="14.0" />
|
||||
</font>
|
||||
<VBox.margin>
|
||||
<Insets top="10.0" />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||
</padding>
|
||||
<HBox.margin>
|
||||
<Insets />
|
||||
</HBox.margin>
|
||||
</VBox>
|
||||
<Region prefHeight="79.0" prefWidth="243.0" HBox.hgrow="ALWAYS" />
|
||||
<Button fx:id="btnCancel" layoutX="391.0" layoutY="38.0" mnemonicParsing="false" style="-fx-background-color: #E74c3c; -fx-cursor: hand; -fx-background-radius: 8;" text="Cancel" 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="btnSave" layoutX="520.0" layoutY="38.0" mnemonicParsing="false" style="-fx-background-color: #3fe06a; -fx-cursor: hand; -fx-background-radius: 8;" text="Save" 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>
|
||||
<padding>
|
||||
<Insets left="15.0" right="15.0" />
|
||||
</padding>
|
||||
</HBox>
|
||||
<VBox prefHeight="370.0" prefWidth="750.0" style="-fx-background-color: white; -fx-background-radius: 14; -fx-border-width: 2; -fx-border-color: #5580b5; -fx-border-radius: 14;">
|
||||
<children>
|
||||
<GridPane hgap="25.0" VBox.vgrow="ALWAYS">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0">
|
||||
<children>
|
||||
<Label text="Product Name:" textFill="#2c3e50">
|
||||
<font>
|
||||
<Font name="System Bold" size="16.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<TextField fx:id="txtProdName" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10;">
|
||||
<padding>
|
||||
<Insets bottom="7.0" left="10.0" right="10.0" top="7.0" />
|
||||
</padding>
|
||||
</TextField>
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<Label text="Product Price:" textFill="#2c3e50">
|
||||
<font>
|
||||
<Font name="System Bold" size="16.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<TextField fx:id="txtProdPrice" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10;">
|
||||
<padding>
|
||||
<Insets bottom="7.0" left="10.0" right="10.0" top="7.0" />
|
||||
</padding>
|
||||
</TextField>
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<Label text="Category:" textFill="#2c3e50">
|
||||
<font>
|
||||
<Font name="System Bold" size="16.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<ComboBox fx:id="cbProdCategory" prefHeight="29.0" prefWidth="336.0" promptText="Select Category" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10; -fx-background-color: white;">
|
||||
<padding>
|
||||
<Insets bottom="3.0" left="10.0" right="10.0" top="3.0" />
|
||||
</padding>
|
||||
</ComboBox>
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.columnIndex="1" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<Label text="Description:" textFill="#2c3e50">
|
||||
<font>
|
||||
<Font name="System Bold" size="16.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<TextField fx:id="txtProdDesc" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10;">
|
||||
<padding>
|
||||
<Insets bottom="7.0" left="10.0" right="10.0" top="7.0" />
|
||||
</padding>
|
||||
</TextField>
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.rowIndex="2" />
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
|
||||
</VBox.margin>
|
||||
</GridPane>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
@@ -68,11 +68,10 @@
|
||||
<TableView fx:id="tvProducts" prefHeight="362.0" prefWidth="752.0" style="-fx-background-color: white; -fx-background-radius: 12;" VBox.vgrow="ALWAYS">
|
||||
<columns>
|
||||
<TableColumn fx:id="colProductId" prefWidth="60.0" text="ID" />
|
||||
<TableColumn fx:id="colProductName" prefWidth="150.0" text="Name" />
|
||||
<TableColumn fx:id="colProductCategory" prefWidth="150.0" text="Category" />
|
||||
<TableColumn fx:id="colProductDesc" prefWidth="220.0" text="Description" />
|
||||
<TableColumn fx:id="colProductPrice" prefWidth="100.0" text="Price" />
|
||||
<TableColumn fx:id="colProductSKU" prefWidth="70.2857666015625" text="SKU" />
|
||||
<TableColumn fx:id="colProductName" prefWidth="170.85714721679688" text="Name" />
|
||||
<TableColumn fx:id="colProductCategory" prefWidth="195.4285888671875" text="Category" />
|
||||
<TableColumn fx:id="colProductDesc" prefWidth="210.28570556640625" text="Description" />
|
||||
<TableColumn fx:id="colProductPrice" prefWidth="115.4285888671875" text="Price" />
|
||||
</columns>
|
||||
</TableView>
|
||||
</children>
|
||||
|
||||
Reference in New Issue
Block a user