Merge conflict resolution and updates

This commit is contained in:
2026-02-24 20:26:50 -07:00
parent 208aaae652
commit 13e8c01a28
38 changed files with 594 additions and 266 deletions

View File

@@ -146,6 +146,14 @@ CREATE TABLE saleItem (
FOREIGN KEY (prodId) REFERENCES product(prodId) FOREIGN KEY (prodId) REFERENCES product(prodId)
); );
CREATE TABLE purchaseOrder (
purchaseOrderId INT AUTO_INCREMENT PRIMARY KEY,
supId INT NOT NULL,
orderDate DATE NOT NULL,
status VARCHAR(50) NOT NULL,
FOREIGN KEY (supId) REFERENCES supplier(supId)
);
CREATE TABLE activityLog ( CREATE TABLE activityLog (
logId INT AUTO_INCREMENT PRIMARY KEY, logId INT AUTO_INCREMENT PRIMARY KEY,
employeeId INT NOT NULL, employeeId INT NOT NULL,
@@ -281,20 +289,97 @@ VALUES
INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId) INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId)
VALUES VALUES
(NOW(), 60.00, 'Card', 2, 1), -- January Sales
('2026-01-28 10:30:00', 50.00, 'Cash', 1, 1), ('2026-01-05 09:15:00', 125.00, 'Card', 1, 1), -- Sale 1: Dog food + treats
('2026-01-29 14:15:00', 120.00, 'Card', 4, 3), ('2026-01-08 11:30:00', 200.00, 'Card', 2, 1), -- Sale 2: Bird cage + fish tank
('2026-01-30 16:45:00', 80.00, 'Card', 2, 2), ('2026-01-12 14:20:00', 60.00, 'Cash', 3, 2), -- Sale 3: Cat toys + hamster wheel
('2026-02-01 11:20:00', 150.00, 'Cash', 5, 4); ('2026-01-15 10:45:00', 150.00, 'Debit', 1, 1), -- Sale 4: Dog food (bulk purchase)
('2026-01-18 16:30:00', 80.00, 'Card', 4, 3), -- Sale 5: Fish tank
('2026-01-22 13:15:00', 95.00, 'Cash', 2, 2), -- Sale 6: Mixed items
('2026-01-25 15:40:00', 240.00, 'Card', 5, 4), -- Sale 7: Two bird cages
('2026-01-28 10:30:00', 80.00, 'Cash', 1, 1), -- Sale 8: Dog food + cat toys
-- February Sales
('2026-02-01 09:00:00', 175.00, 'Card', 3, 3), -- Sale 9: Dog food + treats (bulk)
('2026-02-03 11:20:00', 120.00, 'Card', 2, 1), -- Sale 10: Bird cage
('2026-02-05 14:50:00', 45.00, 'Cash', 4, 2), -- Sale 11: Hamster wheel + cat toys
('2026-02-08 16:15:00', 160.00, 'Debit', 1, 1), -- Sale 12: Fish tank + accessories
('2026-02-10 10:25:00', 100.00, 'Card', 5, 4), -- Sale 13: Dog treats (bulk)
('2026-02-12 13:45:00', 50.00, 'Cash', 2, 2), -- Sale 14: Dog food
('2026-02-15 15:30:00', 85.00, 'Card', 3, 3), -- Sale 15: Mixed pet supplies
('2026-02-18 11:10:00', 200.00, 'Card', 1, 1), -- Sale 16: Bird cage + hamster wheel
('2026-02-20 14:35:00', 155.00, 'Debit', 4, 3), -- Sale 17: Fish tank + cat toys
('2026-02-22 16:50:00', 75.00, 'Cash', 2, 1), -- Sale 18: Dog treats + toys
('2026-02-24 10:15:00', 140.00, 'Card', 5, 4), -- Sale 19: Dog food + treats
(NOW(), 95.00, 'Card', 1, 1); -- Sale 20: Recent sale (current timestamp)
INSERT INTO saleItem (saleId, prodId, quantity, unitPrice) INSERT INTO saleItem (saleId, prodId, quantity, unitPrice)
VALUES VALUES
(1, 2, 2, 10.00), -- Sale 1 items (Dog food + treats)
(2, 1, 1, 50.00), (1, 1, 2, 50.00), -- 2x Premium Dog Food
(3, 3, 1, 120.00), (1, 6, 1, 25.00), -- 1x Organic Dog Treats
(4, 4, 1, 80.00), -- Sale 2 items (Bird cage + fish tank)
(5, 6, 6, 25.00), (2, 3, 1, 120.00), -- 1x Bird Cage Large
(2, 2, 3, 10.00); (2, 4, 1, 80.00), -- 1x Fish Tank 20 Gallon
-- Sale 3 items (Cat toys + hamster wheel)
(3, 2, 3, 10.00), -- 3x Cat Toy Ball
(3, 5, 2, 15.00), -- 2x Hamster Wheel
-- Sale 4 items (Dog food bulk)
(4, 1, 3, 50.00), -- 3x Premium Dog Food
-- Sale 5 items (Fish tank)
(5, 4, 1, 80.00), -- 1x Fish Tank 20 Gallon
-- Sale 6 items (Mixed)
(6, 2, 4, 10.00), -- 4x Cat Toy Ball
(6, 5, 1, 15.00), -- 1x Hamster Wheel
(6, 6, 1, 25.00), -- 1x Organic Dog Treats
(6, 1, 1, 50.00), -- 1x Premium Dog Food (partial - discount applied)
-- Sale 7 items (Two bird cages)
(7, 3, 2, 120.00), -- 2x Bird Cage Large
-- Sale 8 items (Dog food + cat toys)
(8, 1, 1, 50.00), -- 1x Premium Dog Food
(8, 2, 3, 10.00), -- 3x Cat Toy Ball
-- Sale 9 items (Dog food + treats bulk)
(9, 1, 3, 50.00), -- 3x Premium Dog Food
(9, 6, 1, 25.00), -- 1x Organic Dog Treats
-- Sale 10 items (Bird cage)
(10, 3, 1, 120.00), -- 1x Bird Cage Large
-- Sale 11 items (Hamster wheel + cat toys)
(11, 5, 1, 15.00), -- 1x Hamster Wheel
(11, 2, 3, 10.00), -- 3x Cat Toy Ball
-- Sale 12 items (Fish tank + accessories)
(12, 4, 2, 80.00), -- 2x Fish Tank 20 Gallon
-- Sale 13 items (Dog treats bulk)
(13, 6, 4, 25.00), -- 4x Organic Dog Treats
-- Sale 14 items (Dog food)
(14, 1, 1, 50.00), -- 1x Premium Dog Food
-- Sale 15 items (Mixed supplies)
(15, 2, 2, 10.00), -- 2x Cat Toy Ball
(15, 5, 1, 15.00), -- 1x Hamster Wheel
(15, 6, 2, 25.00), -- 2x Organic Dog Treats
-- Sale 16 items (Bird cage + hamster wheel)
(16, 3, 1, 120.00), -- 1x Bird Cage Large
(16, 4, 1, 80.00), -- 1x Fish Tank 20 Gallon
-- Sale 17 items (Fish tank + cat toys)
(17, 4, 1, 80.00), -- 1x Fish Tank 20 Gallon
(17, 1, 1, 50.00), -- 1x Premium Dog Food
(17, 6, 1, 25.00), -- 1x Organic Dog Treats
-- Sale 18 items (Dog treats + toys)
(18, 6, 2, 25.00), -- 2x Organic Dog Treats
(18, 2, 2, 10.00), -- 2x Cat Toy Ball
(18, 5, 1, 15.00), -- 1x Hamster Wheel
-- Sale 19 items (Dog food + treats)
(19, 1, 2, 50.00), -- 2x Premium Dog Food
(19, 6, 2, 25.00), -- 2x Organic Dog Treats (discount applied)
-- Sale 20 items (Recent sale)
(20, 2, 5, 10.00), -- 5x Cat Toy Ball
(20, 5, 3, 15.00); -- 3x Hamster Wheel
INSERT INTO purchaseOrder (supId, orderDate, status)
VALUES
(1, '2025-01-15', 'Delivered'),
(2, '2025-01-20', 'Pending'),
(3, '2025-02-01', 'Delivered'),
(4, '2025-02-10', 'In Transit'),
(1, '2025-02-15', 'Pending');
INSERT INTO activityLog (employeeId, activity) INSERT INTO activityLog (employeeId, activity)
VALUES VALUES

48
README.md Normal file
View File

@@ -0,0 +1,48 @@
# Pet Shop Desktop (JavaFX)
Desktop pet shop management app built with JavaFX and MySQL.
Made by **Group 2**, Shiv, Nikitha, Alex, Harkamal.
## Requirements
- IntelliJ IDEA (Community or Ultimate)
- Java 17+
- Maven (handled through IntelliJ)
- Docker and Docker Compose (for the local MySQL container)
## Database setup (IntelliJ)
1. Open the project in IntelliJ.
2. Open **View → Tool Windows → Services**.
3. Add a Docker connection if needed, then open the **Docker** section in Services.
4. Start the Compose stack from `docker-compose.yml` (Compose Up, or Start).
5. Confirm the `mysql` service is running.
The container uses `mysql:8.4`, creates the `Petstoredb` database, and imports `Petstoredata.sql`.
## App configuration
An example connection file is provided at `connectionpetstore.properties.example`. Copy it to `connectionpetstore.properties` and edit the values to match the local database setup.
## Run the app (IntelliJ, Maven)
1. Open **View → Tool Windows → Maven**.
2. Click **Reload All Maven Projects** if the dependencies have not loaded yet.
3. In the Maven tool window, expand **Plugins → javafx**.
4. Double click **javafx:run**.
Optional, run a clean first:
- In the Maven tool window, expand **Lifecycle** and run **clean**.
## Default accounts
On first run, the app creates a `users` table (if missing) and seeds two accounts:
- Admin: `admin` / `admin123`
- Staff: `staff` / `staff123`
## Notes
- `connectionpetstore.properties` is gitignored so credentials are not committed.
- If the app cannot connect to MySQL, confirm the Compose stack is running and MySQL is available.

View File

@@ -10,7 +10,7 @@
<name>PetShopDesktop</name> <name>PetShopDesktop</name>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<javafx.version>25.0.2</javafx.version> <javafx.version>17.0.10</javafx.version>
<junit.version>5.12.1</junit.version> <junit.version>5.12.1</junit.version>
</properties> </properties>
@@ -53,8 +53,7 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version> <version>3.13.0</version>
<configuration> <configuration>
<source>23</source> <release>17</release>
<target>23</target>
</configuration> </configuration>
</plugin> </plugin>
<plugin> <plugin>

View File

@@ -0,0 +1,93 @@
package org.example.petshopdesktop.DTOs;
import javafx.beans.property.*;
public class SaleDTO {
private IntegerProperty saleId;
private StringProperty saleDate;
private StringProperty employeeName;
private StringProperty productName;
private IntegerProperty quantity;
private DoubleProperty unitPrice;
private DoubleProperty total;
private StringProperty paymentMethod;
public SaleDTO(int saleId, String saleDate, String employeeName, String productName,
int quantity, double unitPrice, double total, String paymentMethod) {
this.saleId = new SimpleIntegerProperty(saleId);
this.saleDate = new SimpleStringProperty(saleDate);
this.employeeName = new SimpleStringProperty(employeeName);
this.productName = new SimpleStringProperty(productName);
this.quantity = new SimpleIntegerProperty(quantity);
this.unitPrice = new SimpleDoubleProperty(unitPrice);
this.total = new SimpleDoubleProperty(total);
this.paymentMethod = new SimpleStringProperty(paymentMethod);
}
// Getters
public int getSaleId() {
return saleId.get();
}
public String getSaleDate() {
return saleDate.get();
}
public String getEmployeeName() {
return employeeName.get();
}
public String getProductName() {
return productName.get();
}
public int getQuantity() {
return quantity.get();
}
public double getUnitPrice() {
return unitPrice.get();
}
public double getTotal() {
return total.get();
}
public String getPaymentMethod() {
return paymentMethod.get();
}
// Properties
public IntegerProperty saleIdProperty() {
return saleId;
}
public StringProperty saleDateProperty() {
return saleDate;
}
public StringProperty employeeNameProperty() {
return employeeName;
}
public StringProperty productNameProperty() {
return productName;
}
public IntegerProperty quantityProperty() {
return quantity;
}
public DoubleProperty unitPriceProperty() {
return unitPrice;
}
public DoubleProperty totalProperty() {
return total;
}
public StringProperty paymentMethodProperty() {
return paymentMethod;
}
}

View File

@@ -1,5 +1,3 @@
//Initial commmit
package org.example.petshopdesktop; package org.example.petshopdesktop;
import javafx.application.Application; import javafx.application.Application;

View File

@@ -3,14 +3,14 @@ package org.example.petshopdesktop;
public class Validator { public class Validator {
/** /**
* Checks if string is not empty * Checks if string is not blank
* @param value string to check * @param value string to check
* @param name name of the input * @param name name of the input
* @return error msg if string is not empty, otherwise empty * @return error msg if string is blank, otherwise empty
*/ */
public static String isPresent(String value, String name){ public static String isPresent(String value, String name){
String msg =""; //OK so far String msg = "";
if(value.isEmpty() || name.isBlank()){ if (value == null || value.isBlank()){
msg += name + " is required. \n"; msg += name + " is required. \n";
} }
return msg; return msg;
@@ -23,7 +23,7 @@ public class Validator {
* @return error msg if input is not a number or negative, otherwise empty * @return error msg if input is not a number or negative, otherwise empty
*/ */
public static String isNonNegativeDouble(String value, String name){ public static String isNonNegativeDouble(String value, String name){
String msg =""; //OK so far String msg ="";
double result; double result;
try{ try{
result = Double.parseDouble(value); result = Double.parseDouble(value);
@@ -40,13 +40,13 @@ public class Validator {
/** /**
* Checks if the input is a double in 2 different range * Checks if the input is a double in 2 different range
* @param value input of string * @param value input of string
* @param name name of inpt * @param name name of input
* @param minValue min value of range * @param minValue min value of range
* @param maxValue max value of range * @param maxValue max value of range
* @return error msg if input is out of range, otherwise empty * @return error msg if input is out of range, otherwise empty
*/ */
public static String isDoubleInRange(String value, String name, double minValue, double maxValue){ public static String isDoubleInRange(String value, String name, double minValue, double maxValue){
String msg =""; //OK so far String msg ="";
double result; double result;
try{ try{
result = Double.parseDouble(value); result = Double.parseDouble(value);
@@ -67,7 +67,7 @@ public class Validator {
* @return error msg if input is not a number or negative, otherwise empty * @return error msg if input is not a number or negative, otherwise empty
*/ */
public static String isNonNegativeInteger(String value, String name){ public static String isNonNegativeInteger(String value, String name){
String msg =""; //OK so far String msg ="";
int result; int result;
try{ try{
result = Integer.parseInt(value); result = Integer.parseInt(value);
@@ -85,6 +85,7 @@ public class Validator {
* check if the string is a given amount of characters or fewer * check if the string is a given amount of characters or fewer
* @param value input of string * @param value input of string
* @param name name of input * @param name name of input
* @param length max allowed length
* @return error msg if input is more than given characters length * @return error msg if input is more than given characters length
*/ */
public static String isLessThanVarChars(String value, String name, int length){ public static String isLessThanVarChars(String value, String name, int length){
@@ -102,8 +103,7 @@ public class Validator {
* @return error msg if input is not a valid email format, otherwise empty * @return error msg if input is not a valid email format, otherwise empty
*/ */
public static String isValidEmail(String value, String name){ public static String isValidEmail(String value, String name){
String msg = ""; //OK so far String msg = "";
// Email regex
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$"; String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
if (!value.matches(regex)){ if (!value.matches(regex)){
@@ -119,8 +119,7 @@ public class Validator {
* @return error msg if input is not in valid phone format, otherwise empty * @return error msg if input is not in valid phone format, otherwise empty
*/ */
public static String isValidPhoneNumber(String value, String name){ public static String isValidPhoneNumber(String value, String name){
String msg = ""; //OK so far String msg = "";
// Phone regex
String regex = "^\\d{3}-\\d{3}-\\d{4}$"; String regex = "^\\d{3}-\\d{3}-\\d{4}$";
if (!value.matches(regex)){ if (!value.matches(regex)){

View File

@@ -1,13 +1,6 @@
package org.example.petshopdesktop.auth; package org.example.petshopdesktop.auth;
/*
Petshop Desktop
Purpose: Application role definitions used by session state and role based access control.
*/
public enum Role { public enum Role {
// Administrative access, includes system management screens.
ADMIN, ADMIN,
// Staff access, limited to day to day operational screens.
STAFF STAFF
} }

View File

@@ -1,24 +1,15 @@
package org.example.petshopdesktop.auth; package org.example.petshopdesktop.auth;
/*
Petshop Desktop
Purpose: In memory session state for the authenticated user.
Notes: Session is process local and cleared on logout or application restart.
*/
public class UserSession { public class UserSession {
// Singleton instance used to share session state across controllers.
private static UserSession instance; private static UserSession instance;
// Current authenticated username, null when logged out.
private String username; private String username;
// Current authenticated role, null when logged out.
private Role role; private Role role;
private UserSession() {} private UserSession() {}
// Lazily initialised singleton accessor.
public static UserSession getInstance() { public static UserSession getInstance() {
if (instance == null) { if (instance == null) {
instance = new UserSession(); instance = new UserSession();
@@ -26,13 +17,11 @@ public class UserSession {
return instance; return instance;
} }
// Stores identity and role for the active session.
public void login(String username, Role role) { public void login(String username, Role role) {
this.username = username; this.username = username;
this.role = role; this.role = role;
} }
// Clears session state and returns the application to an unauthenticated state.
public void logout() { public void logout() {
this.username = null; this.username = null;
this.role = null; this.role = null;
@@ -46,13 +35,10 @@ public class UserSession {
return role; return role;
} }
// Convenience check for administrative privileges.
// Role.ADMIN.equals(role) remains safe when role is null.
public boolean isAdmin() { public boolean isAdmin() {
return Role.ADMIN.equals(role); return Role.ADMIN.equals(role);
} }
// Session is considered active only when both username and role are set.
public boolean isLoggedIn() { public boolean isLoggedIn() {
return username != null && role != null; return username != null && role != null;
} }

View File

@@ -14,10 +14,6 @@ import org.example.petshopdesktop.models.User;
import java.sql.SQLException; import java.sql.SQLException;
/*
Petshop Desktop
Purpose: Authentication controller responsible for validating credentials and initialising the user session.
*/
public class LoginController { public class LoginController {
@FXML @FXML
@@ -31,18 +27,15 @@ public class LoginController {
@FXML @FXML
void btnLoginClicked(ActionEvent event) { void btnLoginClicked(ActionEvent event) {
// Input normalisation keeps authentication behaviour consistent.
String username = txtUsername.getText().trim(); String username = txtUsername.getText().trim();
String password = txtPassword.getText(); String password = txtPassword.getText();
// Basic validation to avoid unnecessary database calls.
if (username.isEmpty() || password.isEmpty()) { if (username.isEmpty() || password.isEmpty()) {
lblError.setText("Please enter username and password."); lblError.setText("Please enter username and password.");
return; return;
} }
try { try {
// Credential verification returns a fully populated User on success.
User user = UserDB.authenticate(username, password); User user = UserDB.authenticate(username, password);
if (user == null) { if (user == null) {
lblError.setText("Invalid username or password."); lblError.setText("Invalid username or password.");
@@ -50,7 +43,6 @@ public class LoginController {
return; return;
} }
// Session state is stored in memory for use by controllers and UI RBAC.
UserSession.getInstance().login(user.getUsername(), user.getRole()); UserSession.getInstance().login(user.getUsername(), user.getRole());
openMainLayout(); openMainLayout();
@@ -61,7 +53,6 @@ public class LoginController {
private void openMainLayout() { private void openMainLayout() {
try { try {
// View transition into the post login application shell.
FXMLLoader loader = new FXMLLoader( FXMLLoader loader = new FXMLLoader(
getClass().getResource("/org/example/petshopdesktop/main-layout-view.fxml")); getClass().getResource("/org/example/petshopdesktop/main-layout-view.fxml"));
Scene scene = new Scene(loader.load()); Scene scene = new Scene(loader.load());

View File

@@ -11,12 +11,23 @@ import javafx.scene.layout.StackPane;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.example.petshopdesktop.auth.UserSession; import org.example.petshopdesktop.auth.UserSession;
/*
Petshop Desktop
Purpose: Main application shell controller, includes navigation and UI level role based access control.
*/
public class MainLayoutController { public class MainLayoutController {
private static final String NAV_BASE_STYLE = "-fx-background-color: transparent; " +
"-fx-text-fill: #cbd5e1; " +
"-fx-background-radius: 10; " +
"-fx-cursor: hand; " +
"-fx-focus-color: transparent; " +
"-fx-faint-focus-color: transparent;";
private static final String NAV_ACTIVE_STYLE = "-fx-background-color: #FF6B6B; " +
"-fx-text-fill: white; " +
"-fx-background-radius: 10; " +
"-fx-cursor: hand; " +
"-fx-focus-color: transparent; " +
"-fx-faint-focus-color: transparent; " +
"-fx-effect: dropshadow(gaussian, rgba(0,0,0,0.22), 10, 0.15, 0, 2);";
@FXML @FXML
private Button btnAdoptions; private Button btnAdoptions;
@@ -124,7 +135,6 @@ public class MainLayoutController {
@FXML @FXML
void btnLogoutClicked(ActionEvent event) { void btnLogoutClicked(ActionEvent event) {
// Logout clears session state before returning to the login view.
UserSession.getInstance().logout(); UserSession.getInstance().logout();
try { try {
FXMLLoader loader = new FXMLLoader( FXMLLoader loader = new FXMLLoader(
@@ -141,22 +151,18 @@ public class MainLayoutController {
@FXML @FXML
public void initialize() { public void initialize() {
// RBAC state is applied once during initial layout load.
applyRBAC(); applyRBAC();
// Default landing view after successful authentication.
loadView("pet-view.fxml"); loadView("pet-view.fxml");
updateButtons(btnPets);
} }
private void applyRBAC() { private void applyRBAC() {
UserSession session = UserSession.getInstance(); UserSession session = UserSession.getInstance();
// Session identity is displayed in the header for clarity and auditing.
lblUsername.setText(session.getUsername()); lblUsername.setText(session.getUsername());
lblRole.setText(session.getRole().toString()); lblRole.setText("Leon's Petstore");
// UI level RBAC hides admin only navigation entries for non admin users.
// setManaged(false) removes the node from layout calculations to avoid empty spacing.
boolean isAdmin = session.isAdmin(); boolean isAdmin = session.isAdmin();
btnInventory.setVisible(isAdmin); btnInventory.setVisible(isAdmin);
btnInventory.setManaged(isAdmin); btnInventory.setManaged(isAdmin);
@@ -165,7 +171,6 @@ public class MainLayoutController {
btnProductSuppliers.setVisible(isAdmin); btnProductSuppliers.setVisible(isAdmin);
btnProductSuppliers.setManaged(isAdmin); btnProductSuppliers.setManaged(isAdmin);
// Privileged operations should still be enforced within the relevant controllers and database methods.
} }
/** /**
@@ -174,10 +179,8 @@ public class MainLayoutController {
*/ */
private void loadView(String fxmlFile) { private void loadView(String fxmlFile) {
try { try {
//Get the location of the fxml for view
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/modelviews/" + fxmlFile)); FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/modelviews/" + fxmlFile));
Parent view = loader.load(); Parent view = loader.load();
//Clear any content that is in the stack pane and add the new view to display
spContentArea.getChildren().clear(); spContentArea.getChildren().clear();
spContentArea.getChildren().add(view); spContentArea.getChildren().add(view);
} catch (Exception e) { } catch (Exception e) {
@@ -191,21 +194,13 @@ public class MainLayoutController {
* @param activeButton the button to be set active * @param activeButton the button to be set active
*/ */
private void updateButtons(Button activeButton) { private void updateButtons(Button activeButton) {
//reset all buttons
Button[] BUTTONS = {btnAdoptions, btnPets, btnAppointments, btnInventory, Button[] BUTTONS = {btnAdoptions, btnPets, btnAppointments, btnInventory,
btnSalesHistory, btnServices, btnSuppliers, btnProductSuppliers, btnProducts}; btnSalesHistory, btnServices, btnSuppliers, btnProductSuppliers, btnProducts, btnPurchaseOrders};
for (Button button : BUTTONS) { for (Button button : BUTTONS) {
//set all buttons to inactive button.setStyle(NAV_BASE_STYLE);
button.setStyle("-fx-background-color: transparent; " +
"-fx-text-fill: #CCCCCC; " +
"-fx-cursor: hand");
} }
//set active button activeButton.setStyle(NAV_ACTIVE_STYLE);
activeButton.setStyle("-fx-background-color: #FF6B6B; " +
"-fx-text-fill: white; " +
"-fx-cursor: hand; " +
"-fx-background-radius: 8");
} }
} }

View File

@@ -1,11 +1,14 @@
package org.example.petshopdesktop.controllers; package org.example.petshopdesktop.controllers;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Button; import javafx.scene.control.*;
import javafx.scene.control.TableColumn; import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.control.TableView; import org.example.petshopdesktop.DTOs.SaleDTO;
import javafx.scene.control.TextField; import org.example.petshopdesktop.database.SaleDB;
import java.sql.SQLException;
public class SaleController { public class SaleController {
@@ -13,38 +16,137 @@ public class SaleController {
private Button btnRefresh; private Button btnRefresh;
@FXML @FXML
private TableColumn<?, ?> colCustomerName; private TableColumn<SaleDTO, String> colCustomerName;
@FXML @FXML
private TableColumn<?, ?> colSaleDate; private TableColumn<SaleDTO, String> colSaleDate;
@FXML @FXML
private TableColumn<?, ?> colSaleId; private TableColumn<SaleDTO, Integer> colSaleId;
@FXML @FXML
private TableColumn<?, ?> colSalePaymentType; private TableColumn<SaleDTO, String> colSalePaymentType;
@FXML @FXML
private TableColumn<?, ?> colSaleQuantity; private TableColumn<SaleDTO, Integer> colSaleQuantity;
@FXML @FXML
private TableColumn<?, ?> colSaleTotal; private TableColumn<SaleDTO, Double> colSaleTotal;
@FXML @FXML
private TableColumn<?, ?> colSaleUnitPrice; private TableColumn<SaleDTO, Double> colSaleUnitPrice;
@FXML @FXML
private TableColumn<?, ?> colServiceProduct; private TableColumn<SaleDTO, String> colServiceProduct;
@FXML @FXML
private TableView<?> tvSales; private TableView<SaleDTO> tvSales;
@FXML @FXML
private TextField txtSearch; private TextField txtSearch;
@FXML private ObservableList<SaleDTO> salesData;
void btnRefresh(ActionEvent event) {
/**
* Initialize the controller - set up table columns and load data
*/
@FXML
public void initialize() {
// Set up table columns
colSaleId.setCellValueFactory(new PropertyValueFactory<>("saleId"));
colSaleDate.setCellValueFactory(new PropertyValueFactory<>("saleDate"));
colCustomerName.setCellValueFactory(new PropertyValueFactory<>("employeeName"));
colServiceProduct.setCellValueFactory(new PropertyValueFactory<>("productName"));
colSaleQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
colSaleUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice"));
colSaleTotal.setCellValueFactory(new PropertyValueFactory<>("total"));
colSalePaymentType.setCellValueFactory(new PropertyValueFactory<>("paymentMethod"));
// Format currency columns
colSaleUnitPrice.setCellFactory(tc -> new TableCell<SaleDTO, Double>() {
@Override
protected void updateItem(Double price, boolean empty) {
super.updateItem(price, empty);
if (empty || price == null) {
setText(null);
} else {
setText(String.format("$%.2f", price));
}
}
});
colSaleTotal.setCellFactory(tc -> new TableCell<SaleDTO, Double>() {
@Override
protected void updateItem(Double total, boolean empty) {
super.updateItem(total, empty);
if (empty || total == null) {
setText(null);
} else {
setText(String.format("$%.2f", total));
}
}
});
// Load initial data
loadSales();
// Add search functionality
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
if (newValue == null || newValue.trim().isEmpty()) {
loadSales();
} else {
searchSales(newValue.trim());
}
});
} }
/**
* Load all sales from database
*/
private void loadSales() {
try {
salesData = SaleDB.getSales();
tvSales.setItems(salesData);
} catch (SQLException e) {
e.printStackTrace();
showError("Failed to load sales data", e.getMessage());
}
}
/**
* Search sales based on filter text
* @param filter search term
*/
private void searchSales(String filter) {
try {
ObservableList<SaleDTO> filteredSales = SaleDB.getFilteredSales(filter);
tvSales.setItems(filteredSales);
} catch (SQLException e) {
e.printStackTrace();
showError("Failed to search sales", e.getMessage());
}
}
/**
* Refresh button handler - reload all sales data
* @param event button click event
*/
@FXML
void btnRefresh(ActionEvent event) {
txtSearch.clear();
loadSales();
}
/**
* Show error alert
* @param title alert title
* @param message error message
*/
private void showError(String title, String message) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setTitle(title);
alert.setHeaderText(null);
alert.setContentText(message);
alert.showAndWait();
}
} }

View File

@@ -115,10 +115,10 @@ public class AdoptionDB {
Connection conn = ConnectionDB.getConnection(); Connection conn = ConnectionDB.getConnection();
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT customerId, firstName, lastName FROM customer"); ResultSet rs = stmt.executeQuery("SELECT customerId, firstName, lastName, email, phone FROM customer");
while (rs.next()) { while (rs.next()) {
customers.add(new Customer(rs.getInt(1), rs.getString(2), rs.getString(3))); customers.add(new Customer(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5)));
} }
conn.close(); conn.close();

View File

@@ -23,7 +23,7 @@ public class ProductSupplierDB {
//Execute Query //Execute Query
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
String sql = "SELECT ps.supId, ps.prodId, s.supCompany, p.prodName, ps.cost " + String sql = "SELECT ps.supId, ps.prodId, s.supCompany, p.prodName, ps.cost " +
"FROM productsupplier ps " + "FROM productSupplier ps " +
"LEFT JOIN product p " + "LEFT JOIN product p " +
"ON p.prodId = ps.prodId " + "ON p.prodId = ps.prodId " +
"LEFT JOIN supplier s " + "LEFT JOIN supplier s " +
@@ -62,7 +62,7 @@ public class ProductSupplierDB {
String sql = String sql =
"SELECT ps.supId, ps.prodId, s.supCompany, p.prodName, ps.cost " + "SELECT ps.supId, ps.prodId, s.supCompany, p.prodName, ps.cost " +
"FROM product p " + "FROM product p " +
"LEFT JOIN productsupplier ps " + "LEFT JOIN productSupplier ps " +
"ON p.prodId = ps.prodId " + "ON p.prodId = ps.prodId " +
"LEFT JOIN supplier s " + "LEFT JOIN supplier s " +
"ON s.supId = ps.supId " + "ON s.supId = ps.supId " +
@@ -108,7 +108,7 @@ public class ProductSupplierDB {
int numRows = 0; int numRows = 0;
Connection conn = ConnectionDB.getConnection(); Connection conn = ConnectionDB.getConnection();
String sql = "INSERT INTO productsupplier (prodId, supId, cost) " + String sql = "INSERT INTO productSupplier (prodId, supId, cost) " +
"VALUES (?, ?, ?)"; "VALUES (?, ?, ?)";
//These are the values from productSupplier to put into query above //These are the values from productSupplier to put into query above
@@ -141,7 +141,7 @@ public class ProductSupplierDB {
try{ try{
//Delete old data first //Delete old data first
String sql = "DELETE FROM productsupplier WHERE supId = ? AND prodId = ?"; String sql = "DELETE FROM productSupplier WHERE supId = ? AND prodId = ?";
PreparedStatement stmt = conn.prepareStatement(sql); PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, oldSupId); stmt.setInt(1, oldSupId);
stmt.setInt(2, oldProdId); stmt.setInt(2, oldProdId);
@@ -149,7 +149,7 @@ public class ProductSupplierDB {
//Then change the data by inserting a new relation with given keys (only if delete worked) //Then change the data by inserting a new relation with given keys (only if delete worked)
if(numRows > 0){ if(numRows > 0){
sql = "INSERT INTO productsupplier (prodId, supId, cost) " + sql = "INSERT INTO productSupplier (prodId, supId, cost) " +
"VALUES (?, ?, ?)"; "VALUES (?, ?, ?)";
stmt = conn.prepareStatement(sql); stmt = conn.prepareStatement(sql);
stmt.setInt(1, productSupplier.getProdId()); stmt.setInt(1, productSupplier.getProdId());
@@ -184,7 +184,7 @@ public class ProductSupplierDB {
int numRows = 0; int numRows = 0;
Connection conn = ConnectionDB.getConnection(); Connection conn = ConnectionDB.getConnection();
String sql = "DELETE FROM productsupplier WHERE supId = ? AND prodId = ?"; String sql = "DELETE FROM productSupplier WHERE supId = ? AND prodId = ?";
PreparedStatement stmt = conn.prepareStatement(sql); PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, supId); stmt.setInt(1, supId);
stmt.setInt(2, prodId); stmt.setInt(2, prodId);

View File

@@ -0,0 +1,113 @@
package org.example.petshopdesktop.database;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import org.example.petshopdesktop.DTOs.SaleDTO;
import java.sql.*;
public class SaleDB {
/**
* Get all sale items with details
* @return ObservableList of SaleDTOs
* @throws SQLException if database operation fails
*/
public static ObservableList<SaleDTO> getSales() throws SQLException {
ObservableList<SaleDTO> sales = FXCollections.observableArrayList();
Connection conn = ConnectionDB.getConnection();
String sql = """
SELECT
s.saleId,
DATE_FORMAT(s.saleDate, '%Y-%m-%d %H:%i') as saleDate,
CONCAT(e.firstName, ' ', e.lastName) as employeeName,
p.prodName,
si.quantity,
si.unitPrice,
(si.quantity * si.unitPrice) as lineTotal,
s.paymentMethod
FROM sale s
JOIN saleItem si ON s.saleId = si.saleId
JOIN product p ON si.prodId = p.prodId
JOIN employee e ON s.employeeId = e.employeeId
ORDER BY s.saleDate DESC, s.saleId, si.saleItemId
""";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
sales.add(new SaleDTO(
rs.getInt("saleId"),
rs.getString("saleDate"),
rs.getString("employeeName"),
rs.getString("prodName"),
rs.getInt("quantity"),
rs.getDouble("unitPrice"),
rs.getDouble("lineTotal"),
rs.getString("paymentMethod")
));
}
conn.close();
return sales;
}
/**
* Get filtered sale items
* @param filter search term
* @return ObservableList of SaleDTOs matching the filter
* @throws SQLException if database operation fails
*/
public static ObservableList<SaleDTO> getFilteredSales(String filter) throws SQLException {
ObservableList<SaleDTO> sales = FXCollections.observableArrayList();
Connection conn = ConnectionDB.getConnection();
String sql = """
SELECT
s.saleId,
DATE_FORMAT(s.saleDate, '%Y-%m-%d %H:%i') as saleDate,
CONCAT(e.firstName, ' ', e.lastName) as employeeName,
p.prodName,
si.quantity,
si.unitPrice,
(si.quantity * si.unitPrice) as lineTotal,
s.paymentMethod
FROM sale s
JOIN saleItem si ON s.saleId = si.saleId
JOIN product p ON si.prodId = p.prodId
JOIN employee e ON s.employeeId = e.employeeId
WHERE s.saleId LIKE ?
OR p.prodName LIKE ?
OR CONCAT(e.firstName, ' ', e.lastName) LIKE ?
OR s.paymentMethod LIKE ?
ORDER BY s.saleDate DESC, s.saleId, si.saleItemId
""";
PreparedStatement pstmt = conn.prepareStatement(sql);
String searchPattern = "%" + filter + "%";
pstmt.setString(1, searchPattern);
pstmt.setString(2, searchPattern);
pstmt.setString(3, searchPattern);
pstmt.setString(4, searchPattern);
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
sales.add(new SaleDTO(
rs.getInt("saleId"),
rs.getString("saleDate"),
rs.getString("employeeName"),
rs.getString("prodName"),
rs.getInt("quantity"),
rs.getDouble("unitPrice"),
rs.getDouble("lineTotal"),
rs.getString("paymentMethod")
));
}
conn.close();
return sales;
}
}

View File

@@ -5,10 +5,6 @@ import org.example.petshopdesktop.models.User;
import java.sql.*; import java.sql.*;
/*
Petshop Desktop
Purpose: User authentication and role lookup against the users table.
*/
public class UserDB { public class UserDB {
/** /**
@@ -34,8 +30,6 @@ public class UserDB {
int userId = rs.getInt("user_id"); int userId = rs.getInt("user_id");
String uname = rs.getString("username"); String uname = rs.getString("username");
// Role values are stored in the database as strings and normalised to match the enum.
// Table constraints limit role values, Role.valueOf is expected to be safe under normal operation.
Role role = Role.valueOf(rs.getString("role").toUpperCase()); Role role = Role.valueOf(rs.getString("role").toUpperCase());
return new User(userId, uname, role); return new User(userId, uname, role);
@@ -59,7 +53,6 @@ public class UserDB {
) )
"""; """;
// Default accounts support initial development and testing, credentials should be rotated or removed for deployment.
String seedAdmin = """ String seedAdmin = """
INSERT IGNORE INTO users (username, password_hash, role) INSERT IGNORE INTO users (username, password_hash, role)
VALUES ('admin', SHA2('admin123', 256), 'ADMIN') VALUES ('admin', SHA2('admin123', 256), 'ADMIN')

View File

@@ -13,7 +13,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?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.AdoptionDialogController"> <VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.AdoptionDialogController">
<children> <children>
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;"> <HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
<children> <children>

View File

@@ -17,7 +17,7 @@
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" <VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0"
spacing="20.0" style="-fx-font-size: 14px;" spacing="20.0" style="-fx-font-size: 14px;"
xmlns="http://javafx.com/javafx/25" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.AppointmentDialogController"> fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.AppointmentDialogController">
<children> <children>
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" <HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0"

View File

@@ -13,7 +13,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?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.InventoryDialogController"> <VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.InventoryDialogController">
<children> <children>
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;"> <HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
<children> <children>

View File

@@ -13,7 +13,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?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.PetDialogController"> <VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.PetDialogController">
<children> <children>
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;"> <HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
<children> <children>

View File

@@ -13,7 +13,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?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"> <VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.ProductDialogController">
<children> <children>
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;"> <HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
<children> <children>

View File

@@ -13,7 +13,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?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.ProductSupplierDialogController"> <VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.ProductSupplierDialogController">
<children> <children>
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;"> <HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
<children> <children>

View File

@@ -13,7 +13,7 @@
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<?import javafx.scene.control.ComboBox?> <?import javafx.scene.control.ComboBox?>
<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.ServiceDialogController"> <VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.ServiceDialogController">
<children> <children>
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;"> <HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
<children> <children>

View File

@@ -12,7 +12,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?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.SupplierDialogController"> <VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController">
<children> <children>
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;"> <HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
<children> <children>

View File

@@ -10,7 +10,7 @@
<VBox alignment="CENTER" prefHeight="400.0" prefWidth="380.0" spacing="16.0" <VBox alignment="CENTER" prefHeight="400.0" prefWidth="380.0" spacing="16.0"
style="-fx-background-color: #2C3E50;" style="-fx-background-color: #2C3E50;"
xmlns="http://javafx.com/javafx/25" xmlns="http://javafx.com/javafx/17"
xmlns:fx="http://javafx.com/fxml/1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="org.example.petshopdesktop.controllers.LoginController"> fx:controller="org.example.petshopdesktop.controllers.LoginController">
<padding> <padding>

View File

@@ -5,131 +5,146 @@
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.Separator?> <?import javafx.scene.control.Separator?>
<?import javafx.scene.layout.BorderPane?> <?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.StackPane?> <?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="742.0" prefWidth="1069.0" xmlns="http://javafx.com/javafx/25" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.MainLayoutController"> <BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="742.0" prefWidth="1069.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.MainLayoutController">
<left> <left>
<VBox prefHeight="700.0" prefWidth="250.0" spacing="15.0" style="-fx-background-color: #2C3E50;" BorderPane.alignment="CENTER"> <VBox prefHeight="700.0" prefWidth="250.0" spacing="10.0" style="-fx-background-color: #2C3E50;" BorderPane.alignment="CENTER">
<padding> <padding>
<Insets bottom="30.0" left="30.0" right="30.0" top="30.0" /> <Insets bottom="22.0" left="22.0" right="22.0" top="24.0" />
</padding> </padding>
<children> <children>
<Label fx:id="lblUsername" text="Name" textFill="WHITE"> <Label fx:id="lblUsername" text="Name" textFill="WHITE">
<font> <font>
<Font name="Comic Sans MS Bold" size="30.0" /> <Font name="System Bold" size="24.0" />
</font> </font>
</Label> </Label>
<Label fx:id="lblRole" text="Pet Store Manager" textFill="#ffe66d"> <Label fx:id="lblRole" text="Leon's Petstore" textFill="#ffe66d">
<font> <font>
<Font name="Comic Sans MS Bold" size="16.0" /> <Font name="System" size="14.0" />
</font> </font>
<padding> <padding>
<Insets bottom="20.0" /> <Insets bottom="8.0" />
</padding> </padding>
</Label> </Label>
<Separator prefWidth="200.0" style="-fx-background-color: #444444;" /> <Separator prefWidth="200.0" style="-fx-background-color: #444444; -fx-opacity: 0.35;" />
<Button fx:id="btnPets" mnemonicParsing="false" onAction="#btnPetsClicked" prefWidth="250.0" style="-fx-background-color: #FF6b6b; -fx-background-radius: 8; -fx-cursor: hand;" text="🐾 Pets" textFill="WHITE">
<VBox.margin> <Label text="PETS" textFill="#94a3b8">
<Insets /> <font>
</VBox.margin> <Font name="System Bold" size="12.0" />
</font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="110.0" top="12.0" /> <Insets top="8.0" />
</padding>
</Label>
<Button fx:id="btnPets" alignment="CENTER_LEFT" mnemonicParsing="false" onAction="#btnPetsClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Pets" textFill="#cbd5e1">
<padding>
<Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
</Button> </Button>
<Button fx:id="btnAdoptions" layoutX="40.0" layoutY="234.0" mnemonicParsing="false" onAction="#btnAdoptionsClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;" text="Adoptions" textFill="#cccccc"> <Button fx:id="btnAdoptions" alignment="CENTER_LEFT" layoutX="40.0" layoutY="234.0" mnemonicParsing="false" onAction="#btnAdoptionsClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Adoptions" textFill="#cbd5e1">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="75.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Button fx:id="btnAppointments" layoutX="40.0" layoutY="294.0" mnemonicParsing="false" onAction="#btnAppointmentsClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;" text="📅 Appointments" textFill="#cccccc"> <Button fx:id="btnAppointments" alignment="CENTER_LEFT" layoutX="40.0" layoutY="294.0" mnemonicParsing="false" onAction="#btnAppointmentsClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Appointments" textFill="#cbd5e1">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="50.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Button fx:id="btnServices" layoutX="40.0" layoutY="354.0" mnemonicParsing="false" onAction="#btnServicesClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;" text="Services" textFill="#cccccc"> <Button fx:id="btnServices" alignment="CENTER_LEFT" layoutX="40.0" layoutY="354.0" mnemonicParsing="false" onAction="#btnServicesClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Services" textFill="#cbd5e1">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="85.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Separator layoutX="40.0" layoutY="156.0" prefWidth="200.0" style="-fx-background-color: #444444;" /> <Separator layoutX="40.0" layoutY="156.0" prefWidth="200.0" style="-fx-background-color: #444444; -fx-opacity: 0.35;" />
<Button fx:id="btnProducts" layoutX="40.0" layoutY="414.0" mnemonicParsing="false" onAction="#btnProductsClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;" text="📦 Products" textFill="#cccccc">
<Label text="PRODUCTS" textFill="#94a3b8">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System Bold" size="12.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="80.0" top="12.0" /> <Insets top="8.0" />
</padding>
</Label>
<Button fx:id="btnProducts" alignment="CENTER_LEFT" layoutX="40.0" layoutY="414.0" mnemonicParsing="false" onAction="#btnProductsClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Products" textFill="#cbd5e1">
<font>
<Font name="System" size="13.0" />
</font>
<padding>
<Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Button fx:id="btnInventory" layoutX="40.0" layoutY="492.0" mnemonicParsing="false" onAction="#btnInventoryClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;" text="📋 Inventory" textFill="#cccccc"> <Button fx:id="btnInventory" alignment="CENTER_LEFT" layoutX="40.0" layoutY="492.0" mnemonicParsing="false" onAction="#btnInventoryClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Inventory" textFill="#cbd5e1">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="74.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Button fx:id="btnSuppliers" layoutX="40.0" layoutY="552.0" mnemonicParsing="false" onAction="#btnSuppliersClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;" text="🏭 Suppliers" textFill="#cccccc"> <Button fx:id="btnSuppliers" alignment="CENTER_LEFT" layoutX="40.0" layoutY="552.0" mnemonicParsing="false" onAction="#btnSuppliersClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Suppliers" textFill="#cbd5e1">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="76.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Button fx:id="btnProductSuppliers" layoutX="40.0" layoutY="612.0" mnemonicParsing="false" onAction="#btnProductSuppliersClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;" text="🔗 Product-Suppliers" textFill="#cccccc"> <Button fx:id="btnProductSuppliers" alignment="CENTER_LEFT" layoutX="40.0" layoutY="612.0" mnemonicParsing="false" onAction="#btnProductSuppliersClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Product-Suppliers" textFill="#cbd5e1">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="18.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Button fx:id="btnSalesHistory" layoutX="40.0" layoutY="672.0" mnemonicParsing="false" onAction="#btnSalesHistoryClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;" text="📄 Sales History" textFill="#cccccc"> <Button fx:id="btnSalesHistory" alignment="CENTER_LEFT" layoutX="40.0" layoutY="672.0" mnemonicParsing="false" onAction="#btnSalesHistoryClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Sales History" textFill="#cbd5e1">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="45.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Button fx:id="btnPurchaseOrders" <Button fx:id="btnPurchaseOrders" alignment="CENTER_LEFT" mnemonicParsing="false" onAction="#btnPurchaseOrdersClicked" prefWidth="250.0" style="-fx-background-color: transparent; -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Purchase Orders" textFill="#cbd5e1">
mnemonicParsing="false"
onAction="#btnPurchaseOrdersClicked"
prefWidth="250.0"
style="-fx-background-color: transparent; -fx-background-radius: 8; -fx-cursor: hand;"
text="🧾 Purchase Orders"
textFill="#cccccc">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="40.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
</Button> </Button>
<Button fx:id="btnLogout" mnemonicParsing="false" onAction="#btnLogoutClicked" prefWidth="250.0" style="-fx-background-color: #34495E; -fx-background-radius: 8; -fx-cursor: hand;" text="🚪 Logout" textFill="#cccccc">
<Region VBox.vgrow="ALWAYS" />
<Button fx:id="btnLogout" alignment="CENTER_LEFT" mnemonicParsing="false" onAction="#btnLogoutClicked" prefWidth="250.0" style="-fx-background-color: rgba(255,255,255,0.08); -fx-background-radius: 10; -fx-cursor: hand; -fx-focus-color: transparent; -fx-faint-focus-color: transparent;" text="Logout" textFill="#e2e8f0">
<font> <font>
<Font name="Comic Sans MS Bold" size="14.0" /> <Font name="System" size="13.0" />
</font> </font>
<padding> <padding>
<Insets bottom="12.0" left="12.0" right="94.0" top="12.0" /> <Insets bottom="10.0" left="14.0" right="14.0" top="10.0" />
</padding> </padding>
<VBox.margin> <VBox.margin>
<Insets top="20.0" /> <Insets top="12.0" />
</VBox.margin> </VBox.margin>
</Button> </Button>
</children> </children>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.AdoptionController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.AdoptionController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.AppointmentController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.AppointmentController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.InventoryController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.InventoryController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.PetController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.PetController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.ProductSupplierController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.ProductSupplierController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.ProductController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.ProductController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>

View File

@@ -7,7 +7,7 @@
<VBox spacing="20.0" <VBox spacing="20.0"
style="-fx-font-size: 14px;" style="-fx-font-size: 14px;"
xmlns="http://javafx.com/javafx/25" xmlns="http://javafx.com/javafx/17"
xmlns:fx="http://javafx.com/fxml/1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="org.example.petshopdesktop.controllers.PurchaseOrderController"> fx:controller="org.example.petshopdesktop.controllers.PurchaseOrderController">

View File

@@ -1,82 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Region?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity"
minWidth="-Infinity"
spacing="20"
style="-fx-font-size:14px;"
xmlns="http://javafx.com/javafx/25"
xmlns:fx="http://javafx.com/fxml/1"
fx:controller="org.example.petshopdesktop.controllers.PurchaseOrderdialogController">
<padding>
<Insets top="20" right="20" bottom="20" left="20"/>
</padding>
<!-- HEADER -->
<HBox alignment="CENTER_LEFT" spacing="20">
<Label text="Purchase Orders" textFill="#2c3e50">
<font>
<Font name="System Bold" size="30"/>
</font>
</Label>
<Region HBox.hgrow="ALWAYS"/>
</HBox>
<!-- SEARCH BAR -->
<HBox alignment="CENTER_LEFT"
spacing="10"
style="-fx-background-color:white; -fx-background-radius:14;">
<padding>
<Insets top="10" bottom="10" left="15" right="15"/>
</padding>
<TextField fx:id="txtSearch"
promptText="Search Purchase Orders..."
style="-fx-border-width:0; -fx-background-color:transparent;"
HBox.hgrow="ALWAYS"/>
</HBox>
<!-- TABLE -->
<TableView fx:id="tvPurchaseOrders"
prefHeight="362"
style="-fx-background-color:white; -fx-background-radius:12;"
VBox.vgrow="ALWAYS">
<columns>
<TableColumn fx:id="colOrderId"
text="Order ID"
prefWidth="120"/>
<TableColumn fx:id="colSupplier"
text="Supplier"
prefWidth="250"/>
<TableColumn fx:id="colOrderDate"
text="Order Date"
prefWidth="200"/>
<TableColumn fx:id="colStatus"
text="Status"
prefWidth="180"/>
</columns>
</TableView>
</VBox>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.SaleController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.SaleController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.ServiceController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.ServiceController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>

View File

@@ -11,7 +11,7 @@
<?import javafx.scene.layout.VBox?> <?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?> <?import javafx.scene.text.Font?>
<VBox minHeight="-Infinity" minWidth="-Infinity" 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.SupplierController"> <VBox minHeight="-Infinity" minWidth="-Infinity" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.SupplierController">
<padding> <padding>
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" /> <Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
</padding> </padding>