Added CRUD to Products and added Validation to dialog
This commit is contained in:
215
Petstoredata.sql
215
Petstoredata.sql
@@ -7,24 +7,24 @@ USE Petstoredb;
|
||||
CREATE TABLE storeLocation (
|
||||
storeId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
storeName VARCHAR(100) NOT NULL,
|
||||
address VARCHAR(255),
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100)
|
||||
address VARCHAR(255) NOT NULL,
|
||||
phone VARCHAR(20) NOT NULL,
|
||||
email VARCHAR(100) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE employee (
|
||||
employeeId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
firstName VARCHAR(50) NOT NULL,
|
||||
lastName VARCHAR(50) NOT NULL,
|
||||
email VARCHAR(100),
|
||||
phone VARCHAR(20),
|
||||
role VARCHAR(50),
|
||||
isActive BOOLEAN DEFAULT TRUE
|
||||
email VARCHAR(100) NOT NULL,
|
||||
phone VARCHAR(20) NOT NULL,
|
||||
role VARCHAR(50) NOT NULL,
|
||||
isActive BOOLEAN DEFAULT TRUE NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE employeeStore (
|
||||
employeeId INT,
|
||||
storeId INT,
|
||||
employeeId INT NOT NULL,
|
||||
storeId INT NOT NULL,
|
||||
PRIMARY KEY (employeeId, storeId),
|
||||
FOREIGN KEY (employeeId) REFERENCES employee(employeeId),
|
||||
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId)
|
||||
@@ -34,26 +34,26 @@ CREATE TABLE customer (
|
||||
customerId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
firstName VARCHAR(50) NOT NULL,
|
||||
lastName VARCHAR(50) NOT NULL,
|
||||
email VARCHAR(100),
|
||||
phone VARCHAR(20)
|
||||
email VARCHAR(100) NOT NULL,
|
||||
phone VARCHAR(20) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE pet (
|
||||
petId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
petName VARCHAR(50),
|
||||
petSpecies VARCHAR(50),
|
||||
petBreed VARCHAR(50),
|
||||
petAge INT,
|
||||
petStatus VARCHAR(20),
|
||||
petPrice DECIMAL(10, 2)
|
||||
petName VARCHAR(50) NOT NULL,
|
||||
petSpecies VARCHAR(50) NOT NULL,
|
||||
petBreed VARCHAR(50) NOT NULL,
|
||||
petAge INT NOT NULL,
|
||||
petStatus VARCHAR(20) NOT NULL,
|
||||
petPrice DECIMAL(10, 2) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE adoption (
|
||||
adoptionId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
petId INT,
|
||||
customerId INT,
|
||||
adoptionDate DATE,
|
||||
adoptionStatus VARCHAR(20),
|
||||
petId INT NOT NULL,
|
||||
customerId INT NOT NULL,
|
||||
adoptionDate DATE NOT NULL,
|
||||
adoptionStatus VARCHAR(20) NOT NULL,
|
||||
FOREIGN KEY (petId) REFERENCES pet(petId),
|
||||
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
||||
);
|
||||
@@ -61,31 +61,30 @@ CREATE TABLE adoption (
|
||||
CREATE TABLE supplier (
|
||||
supId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
supCompany VARCHAR(100) NOT NULL,
|
||||
supContactFirstName VARCHAR(50),
|
||||
supContactLastName VARCHAR(50),
|
||||
supEmail VARCHAR(100),
|
||||
supPhone VARCHAR(20)
|
||||
supContactFirstName VARCHAR(50) NOT NULL,
|
||||
supContactLastName VARCHAR(50) NOT NULL,
|
||||
supEmail VARCHAR(100) NOT NULL,
|
||||
supPhone VARCHAR(20) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE category (
|
||||
categoryId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
categoryName VARCHAR(100) NOT NULL,
|
||||
categoryType VARCHAR(50)
|
||||
categoryType VARCHAR(50) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE product (
|
||||
prodId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
prodName VARCHAR(100) NOT NULL,
|
||||
prodSku VARCHAR(50) UNIQUE,
|
||||
prodPrice DECIMAL(10, 2),
|
||||
categoryId INT,
|
||||
prodPrice DECIMAL(10, 2) NOT NULL,
|
||||
categoryId INT NOT NULL,
|
||||
prodDesc TEXT,
|
||||
FOREIGN KEY (categoryId) REFERENCES category(categoryId)
|
||||
);
|
||||
|
||||
CREATE TABLE productSupplier (
|
||||
supId INT,
|
||||
prodId INT,
|
||||
supId INT NOT NULL,
|
||||
prodId INT NOT NULL,
|
||||
PRIMARY KEY (supId, prodId),
|
||||
FOREIGN KEY (supId) REFERENCES supplier(supId),
|
||||
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||
@@ -93,8 +92,8 @@ CREATE TABLE productSupplier (
|
||||
|
||||
CREATE TABLE inventory (
|
||||
inventoryId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
prodId INT,
|
||||
quantity INT DEFAULT 0,
|
||||
prodId INT NOT NULL,
|
||||
quantity INT DEFAULT 0 NOT NULL,
|
||||
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||
);
|
||||
|
||||
@@ -102,24 +101,24 @@ CREATE TABLE service (
|
||||
serviceId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
serviceName VARCHAR(100) NOT NULL,
|
||||
serviceDesc TEXT,
|
||||
serviceDuration INT,
|
||||
servicePrice DECIMAL(10, 2)
|
||||
serviceDuration INT NOT NULL,
|
||||
servicePrice DECIMAL(10, 2) NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE appointment (
|
||||
appointmentId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
serviceId INT,
|
||||
customerId INT,
|
||||
appointmentDate DATE,
|
||||
appointmentTime TIME,
|
||||
appointmentStatus VARCHAR(20),
|
||||
serviceId INT NOT NULL,
|
||||
customerId INT NOT NULL,
|
||||
appointmentDate DATE NOT NULL,
|
||||
appointmentTime TIME NOT NULL,
|
||||
appointmentStatus VARCHAR(20) NOT NULL,
|
||||
FOREIGN KEY (serviceId) REFERENCES service(serviceId),
|
||||
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
||||
);
|
||||
|
||||
CREATE TABLE appointmentPet (
|
||||
appointmentId INT,
|
||||
petId INT,
|
||||
appointmentId INT NOT NULL,
|
||||
petId INT NOT NULL,
|
||||
PRIMARY KEY (appointmentId, petId),
|
||||
FOREIGN KEY (appointmentId) REFERENCES appointment(appointmentId),
|
||||
FOREIGN KEY (petId) REFERENCES pet(petId)
|
||||
@@ -127,30 +126,30 @@ CREATE TABLE appointmentPet (
|
||||
|
||||
CREATE TABLE sale (
|
||||
saleId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
saleDate DATETIME,
|
||||
totalAmount DECIMAL(10, 2),
|
||||
paymentMethod VARCHAR(50),
|
||||
employeeId INT,
|
||||
storeId INT,
|
||||
saleDate DATETIME NOT NULL,
|
||||
totalAmount DECIMAL(10, 2) NOT NULL,
|
||||
paymentMethod VARCHAR(50) NOT NULL,
|
||||
employeeId INT NOT NULL,
|
||||
storeId INT NOT NULL,
|
||||
FOREIGN KEY (employeeId) REFERENCES employee(employeeId),
|
||||
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId)
|
||||
);
|
||||
|
||||
CREATE TABLE saleItem (
|
||||
saleItemId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
saleId INT,
|
||||
prodId INT,
|
||||
quantity INT,
|
||||
unitPrice DECIMAL(10, 2),
|
||||
saleId INT NOT NULL,
|
||||
prodId INT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unitPrice DECIMAL(10, 2) NOT NULL,
|
||||
FOREIGN KEY (saleId) REFERENCES sale(saleId),
|
||||
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||
);
|
||||
|
||||
CREATE TABLE activityLog (
|
||||
logId INT AUTO_INCREMENT PRIMARY KEY,
|
||||
employeeId INT,
|
||||
activity TEXT,
|
||||
logTimestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
employeeId INT NOT NULL,
|
||||
activity TEXT NOT NULL,
|
||||
logTimestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
FOREIGN KEY (employeeId) REFERENCES employee(employeeId)
|
||||
);
|
||||
|
||||
@@ -159,78 +158,148 @@ CREATE TABLE activityLog (
|
||||
INSERT INTO storeLocation (storeName, address, phone, email)
|
||||
VALUES
|
||||
('Downtown Branch', '123 Main St', '123-456-7890', 'downtown@petshop.com'),
|
||||
('North Branch', '456 North Ave', '987-654-3210', 'north@petshop.com');
|
||||
('North Branch', '456 North Ave', '987-654-3210', 'north@petshop.com'),
|
||||
('West Side Store', '789 West Blvd', '555-123-4567', 'westside@petshop.com'),
|
||||
('East End Shop', '321 East Road', '555-987-6543', 'eastend@petshop.com'),
|
||||
('South Mall Location', '654 South Plaza', '555-246-8135', 'southmall@petshop.com');
|
||||
|
||||
INSERT INTO employee (firstName, lastName, email, phone, role, isActive)
|
||||
VALUES
|
||||
('John', 'Doe', 'john@petshop.com', '111-222-3333', 'Manager', TRUE),
|
||||
('Sara', 'Smith', 'sara@petshop.com', '444-555-6666', 'Staff', TRUE);
|
||||
('Sara', 'Smith', 'sara@petshop.com', '444-555-6666', 'Staff', TRUE),
|
||||
('Michael', 'Johnson', 'michael@petshop.com', '222-333-4444', 'Groomer', TRUE),
|
||||
('Lisa', 'Williams', 'lisa@petshop.com', '333-444-5555', 'Staff', TRUE),
|
||||
('David', 'Brown', 'david@petshop.com', '555-666-7777', 'Veterinarian', TRUE),
|
||||
('Emma', 'Davis', 'emma@petshop.com', '666-777-8888', 'Manager', FALSE);
|
||||
|
||||
INSERT INTO employeeStore (employeeId, storeId)
|
||||
VALUES
|
||||
(1, 1),
|
||||
(2, 1),
|
||||
(2, 2);
|
||||
(2, 2),
|
||||
(3, 2),
|
||||
(4, 3),
|
||||
(5, 1),
|
||||
(5, 4),
|
||||
(6, 5);
|
||||
|
||||
INSERT INTO customer (firstName, lastName, email, phone)
|
||||
VALUES
|
||||
('Alex', 'Brown', 'alex@gmail.com', '777-888-9999'),
|
||||
('Emily', 'Clark', 'emily@gmail.com', '666-555-4444');
|
||||
('Emily', 'Clark', 'emily@gmail.com', '666-555-4444'),
|
||||
('James', 'Wilson', 'james@gmail.com', '888-999-0000'),
|
||||
('Olivia', 'Martinez', 'olivia@gmail.com', '999-000-1111'),
|
||||
('William', 'Anderson', 'william@gmail.com', '000-111-2222'),
|
||||
('Sophia', 'Taylor', 'sophia@gmail.com', '111-222-3333');
|
||||
|
||||
INSERT INTO pet (petName, petSpecies, petBreed, petAge, petStatus, petPrice)
|
||||
VALUES
|
||||
('Buddy', 'Dog', 'Labrador', 2, 'Available', 500.00),
|
||||
('Milo', 'Cat', 'Persian', 1, 'Available', 300.00);
|
||||
('Milo', 'Cat', 'Persian', 1, 'Available', 300.00),
|
||||
('Charlie', 'Dog', 'Golden Retriever', 3, 'Available', 550.00),
|
||||
('Luna', 'Cat', 'Siamese', 2, 'Adopted', 350.00),
|
||||
('Max', 'Dog', 'Beagle', 1, 'Available', 450.00),
|
||||
('Bella', 'Cat', 'Maine Coon', 4, 'Available', 400.00);
|
||||
|
||||
INSERT INTO adoption (petId, customerId, adoptionDate, adoptionStatus)
|
||||
VALUES
|
||||
(1, 1, '2026-01-15', 'Completed');
|
||||
(1, 1, '2026-01-15', 'Completed'),
|
||||
(4, 3, '2026-01-20', 'Completed'),
|
||||
(2, 2, '2026-01-25', 'Pending'),
|
||||
(5, 4, '2026-02-01', 'Completed'),
|
||||
(6, 5, '2026-02-02', 'Pending');
|
||||
|
||||
INSERT INTO supplier (supCompany, supContactFirstName, supContactLastName, supEmail, supPhone)
|
||||
VALUES
|
||||
('PetFood Inc', 'Robert', 'King', 'contact@petfood.com', '888-111-2222');
|
||||
('PetFood Inc', 'Robert', 'King', 'contact@petfood.com', '888-111-2222'),
|
||||
('Toy World', 'Jennifer', 'Lee', 'sales@toyworld.com', '888-222-3333'),
|
||||
('Pet Supplies Co', 'Kevin', 'White', 'info@petsupplies.com', '888-333-4444'),
|
||||
('Animal Care Products', 'Nancy', 'Green', 'orders@animalcare.com', '888-444-5555'),
|
||||
('Premium Pet Goods', 'Tom', 'Black', 'support@premiumpet.com', '888-555-6666');
|
||||
|
||||
INSERT INTO category (categoryName, categoryType)
|
||||
VALUES
|
||||
('Dog Food', 'Product'),
|
||||
('Cat Toys', 'Product');
|
||||
('Cat Toys', 'Product'),
|
||||
('Bird Supplies', 'Product'),
|
||||
('Aquarium', 'Product'),
|
||||
('Small Animals', 'Product');
|
||||
|
||||
INSERT INTO product (prodName, prodSku, prodPrice, categoryId, prodDesc)
|
||||
INSERT INTO product (prodName, prodPrice, categoryId, prodDesc)
|
||||
VALUES
|
||||
('Premium Dog Food', 'DF001', 50.00, 1, 'High quality dog food'),
|
||||
('Cat Toy Ball', 'CT001', 10.00, 2, 'Colorful toy for cats');
|
||||
('Premium Dog Food', 50.00, 1, 'High quality dog food'),
|
||||
('Cat Toy Ball', 10.00, 2, 'Colorful toy for cats'),
|
||||
('Bird Cage Large', 120.00, 3, 'Spacious bird cage'),
|
||||
('Fish Tank 20 Gallon', 80.00, 4, 'Complete aquarium kit'),
|
||||
('Hamster Wheel', 15.00, 5, 'Exercise wheel for small pets'),
|
||||
('Organic Dog Treats', 25.00, 1, 'Natural dog treats');
|
||||
|
||||
INSERT INTO productSupplier (supId, prodId)
|
||||
VALUES
|
||||
(1, 1),
|
||||
(1, 2);
|
||||
(1, 2),
|
||||
(2, 2),
|
||||
(3, 3),
|
||||
(3, 4),
|
||||
(4, 5),
|
||||
(5, 6),
|
||||
(1, 6);
|
||||
|
||||
INSERT INTO inventory (prodId, quantity)
|
||||
VALUES
|
||||
(1, 100),
|
||||
(2, 200);
|
||||
(2, 200),
|
||||
(3, 50),
|
||||
(4, 30),
|
||||
(5, 150),
|
||||
(6, 75);
|
||||
|
||||
INSERT INTO service (serviceName, serviceDesc, serviceDuration, servicePrice)
|
||||
VALUES
|
||||
('Pet Grooming', 'Full grooming service', 60, 40.00);
|
||||
('Pet Grooming', 'Full grooming service', 60, 40.00),
|
||||
('Nail Trimming', 'Quick nail trim', 15, 10.00),
|
||||
('Bath and Brush', 'Bathing and brushing service', 45, 30.00),
|
||||
('Veterinary Checkup', 'Complete health examination', 30, 75.00),
|
||||
('Teeth Cleaning', 'Professional dental cleaning', 90, 100.00);
|
||||
|
||||
INSERT INTO appointment (serviceId, customerId, appointmentDate, appointmentTime, appointmentStatus)
|
||||
VALUES
|
||||
(1, 2, '2026-02-01', '10:30:00', 'Booked');
|
||||
(1, 2, '2026-02-01', '10:30:00', 'Booked'),
|
||||
(2, 1, '2026-02-03', '14:00:00', 'Booked'),
|
||||
(3, 3, '2026-02-05', '09:00:00', 'Completed'),
|
||||
(4, 4, '2026-02-07', '11:30:00', 'Booked'),
|
||||
(5, 5, '2026-02-10', '15:00:00', 'Cancelled');
|
||||
|
||||
INSERT INTO appointmentPet (appointmentId, petId)
|
||||
VALUES
|
||||
(1, 2);
|
||||
(1, 2),
|
||||
(2, 1),
|
||||
(3, 3),
|
||||
(4, 5),
|
||||
(5, 6);
|
||||
|
||||
INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId)
|
||||
VALUES
|
||||
(NOW(), 60.00, 'Card', 2, 1);
|
||||
(NOW(), 60.00, 'Card', 2, 1),
|
||||
('2026-01-28 10:30:00', 50.00, 'Cash', 1, 1),
|
||||
('2026-01-29 14:15:00', 120.00, 'Card', 4, 3),
|
||||
('2026-01-30 16:45:00', 80.00, 'Card', 2, 2),
|
||||
('2026-02-01 11:20:00', 150.00, 'Cash', 5, 4);
|
||||
|
||||
INSERT INTO saleItem (saleId, prodId, quantity, unitPrice)
|
||||
VALUES
|
||||
(1, 2, 2, 10.00);
|
||||
(1, 2, 2, 10.00),
|
||||
(2, 1, 1, 50.00),
|
||||
(3, 3, 1, 120.00),
|
||||
(4, 4, 1, 80.00),
|
||||
(5, 6, 6, 25.00),
|
||||
(2, 2, 3, 10.00);
|
||||
|
||||
INSERT INTO activityLog (employeeId, activity)
|
||||
VALUES
|
||||
(1, 'Created new sale'),
|
||||
(2, 'Booked appointment');
|
||||
(2, 'Booked appointment'),
|
||||
(3, 'Completed grooming service'),
|
||||
(4, 'Processed inventory order'),
|
||||
(5, 'Conducted health checkup'),
|
||||
(1, 'Updated customer information');
|
||||
@@ -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