diff --git a/log.txt b/log.txt new file mode 100644 index 00000000..0f8af08e --- /dev/null +++ b/log.txt @@ -0,0 +1,14 @@ +[2026-02-25 11:54:59] [INSERT] DB_INSERT | Table: sale | ID: Sale ID: 22 | Details: Created sale with 1 items, total: $240.00 +[2026-02-25 11:55:37] [INSERT] DB_INSERT | Table: sale | ID: Sale ID: 23 | Details: Created sale with 1 items, total: $240.00 +[2026-02-28 14:29:17] [ERROR] EXCEPTION | Location: ConnectionDB.getConnection | Type: CommunicationsException | Message: Communications link failure + +The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. | Context: Establishing database connection +[2026-02-28 14:29:17] [ERROR] EXCEPTION | Location: ConnectionDB.getConnection | Type: CommunicationsException | Message: Communications link failure + +The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. | Context: Establishing database connection +[2026-02-28 14:30:29] [ERROR] EXCEPTION | Location: MainLayoutController.loadView | Type: LoadException | Message: +/home/user/Documents/SAIT/Winter%202026/intellij/group-2-threaded-project-petshop-desktop/target/classes/org/example/petshopdesktop/modelviews/analytics-view.fxml:58 + | Context: Loading view: analytics-view.fxml +[2026-02-28 14:35:14] [ERROR] EXCEPTION | Location: MainLayoutController.loadView | Type: LoadException | Message: +/home/user/Documents/SAIT/Winter%202026/intellij/group-2-threaded-project-petshop-desktop/target/classes/org/example/petshopdesktop/modelviews/analytics-view.fxml:58 + | Context: Loading view: analytics-view.fxml diff --git a/src/main/java/org/example/petshopdesktop/controllers/AnalyticsController.java b/src/main/java/org/example/petshopdesktop/controllers/AnalyticsController.java new file mode 100644 index 00000000..0624effb --- /dev/null +++ b/src/main/java/org/example/petshopdesktop/controllers/AnalyticsController.java @@ -0,0 +1,176 @@ +package org.example.petshopdesktop.controllers; + +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.chart.*; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import org.example.petshopdesktop.auth.UserSession; +import org.example.petshopdesktop.database.SaleDB; +import org.example.petshopdesktop.models.analytics.*; +import org.example.petshopdesktop.util.ActivityLogger; + +import java.text.NumberFormat; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +public class AnalyticsController { + + @FXML + private Button btnRefresh; + + @FXML + private Label lblError; + + @FXML + private Label lblTotalRevenue; + + @FXML + private Label lblTotalTransactions; + + @FXML + private Label lblAvgTransaction; + + @FXML + private Label lblTotalItems; + + @FXML + private LineChart chartSalesOverTime; + + @FXML + private BarChart chartTopRevenue; + + @FXML + private BarChart chartTopQuantity; + + @FXML + private PieChart chartPaymentMethods; + + @FXML + private BarChart chartEmployeePerformance; + + private final NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CANADA); + private final NumberFormat wholeNumber = NumberFormat.getIntegerInstance(); + + @FXML + public void initialize() { + configureCharts(); + loadAnalyticsData(); + } + + private void disableAllCharts() { + chartSalesOverTime.setVisible(false); + chartTopRevenue.setVisible(false); + chartTopQuantity.setVisible(false); + chartPaymentMethods.setVisible(false); + chartEmployeePerformance.setVisible(false); + btnRefresh.setDisable(true); + } + + private void configureCharts() { + chartSalesOverTime.setAnimated(true); + chartTopRevenue.setAnimated(true); + chartTopQuantity.setAnimated(true); + chartPaymentMethods.setAnimated(true); + chartEmployeePerformance.setAnimated(true); + } + + private void loadAnalyticsData() { + lblError.setVisible(false); + try { + loadSummaryData(); + loadSalesOverTime(); + loadTopProductsByRevenue(); + loadTopProductsByQuantity(); + loadPaymentMethodDistribution(); + loadEmployeePerformance(); + } catch (Exception e) { + ActivityLogger.getInstance().logException("AnalyticsController.loadAnalyticsData", e, "Loading analytics data"); + lblError.setText("Error loading analytics data. Please try again."); + lblError.setVisible(true); + } + } + + private void loadSummaryData() throws Exception { + SalesSummary summary = SaleDB.getSalesSummary(); + if (summary != null) { + lblTotalRevenue.setText(currency.format(summary.getTotalRevenue())); + lblTotalTransactions.setText(wholeNumber.format(summary.getTotalTransactions())); + lblAvgTransaction.setText(currency.format(summary.getAvgTransactionValue())); + lblTotalItems.setText(wholeNumber.format(summary.getTotalItemsSold())); + } + } + + private void loadSalesOverTime() throws Exception { + ObservableList data = SaleDB.getDailySalesRevenue(); + XYChart.Series series = new XYChart.Series<>(); + series.setName("Daily Revenue"); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd"); + for (DailySalesData dailySale : data) { + String dateStr = dailySale.getDate().format(formatter); + series.getData().add(new XYChart.Data<>(dateStr, dailySale.getRevenue())); + } + + chartSalesOverTime.getData().clear(); + chartSalesOverTime.getData().add(series); + } + + private void loadTopProductsByRevenue() throws Exception { + ObservableList data = SaleDB.getTopProductsByRevenue(10); + XYChart.Series series = new XYChart.Series<>(); + series.setName("Revenue"); + + for (ProductSalesData product : data) { + series.getData().add(new XYChart.Data<>(product.getTotalRevenue(), product.getProductName())); + } + + chartTopRevenue.getData().clear(); + chartTopRevenue.getData().add(series); + } + + private void loadTopProductsByQuantity() throws Exception { + ObservableList data = SaleDB.getTopProductsByQuantity(10); + XYChart.Series series = new XYChart.Series<>(); + series.setName("Quantity"); + + for (ProductSalesData product : data) { + series.getData().add(new XYChart.Data<>(product.getTotalQuantity(), product.getProductName())); + } + + chartTopQuantity.getData().clear(); + chartTopQuantity.getData().add(series); + } + + private void loadPaymentMethodDistribution() throws Exception { + ObservableList data = SaleDB.getPaymentMethodDistribution(); + chartPaymentMethods.getData().clear(); + + for (PaymentMethodData payment : data) { + PieChart.Data slice = new PieChart.Data( + payment.getPaymentMethod() + " (" + payment.getTransactionCount() + ")", + payment.getTransactionCount() + ); + chartPaymentMethods.getData().add(slice); + } + } + + private void loadEmployeePerformance() throws Exception { + ObservableList data = SaleDB.getEmployeeSalesPerformance(); + XYChart.Series series = new XYChart.Series<>(); + series.setName("Revenue"); + + for (EmployeeSalesData employee : data) { + series.getData().add(new XYChart.Data<>(employee.getEmployeeName(), employee.getTotalRevenue())); + } + + chartEmployeePerformance.getData().clear(); + chartEmployeePerformance.getData().add(series); + } + + @FXML + void handleRefresh(ActionEvent event) { + loadAnalyticsData(); + } +} diff --git a/src/main/java/org/example/petshopdesktop/controllers/LoginController.java b/src/main/java/org/example/petshopdesktop/controllers/LoginController.java index e39b2ea3..502c7a49 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/LoginController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/LoginController.java @@ -29,9 +29,6 @@ public class LoginController { @FXML private Label lblError; - @FXML - private Button btnCreateStaff; - @FXML public void initialize() { lblError.setText(""); @@ -93,24 +90,6 @@ public class LoginController { } } - @FXML - void btnCreateStaffClicked(ActionEvent event) { - lblError.setText(""); - try { - FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/staff-register-dialog-view.fxml")); - Stage dialog = new Stage(); - dialog.initOwner(txtUsername.getScene().getWindow()); - dialog.initModality(Modality.APPLICATION_MODAL); - dialog.setTitle("Create Staff Account"); - dialog.setScene(new Scene(loader.load())); - dialog.setResizable(false); - dialog.showAndWait(); - } catch (Exception e) { - ActivityLogger.getInstance().logException("LoginController.btnCreateStaffClicked", e, "Opening staff register dialog"); - lblError.setText("Could not open staff account creation."); - } - } - private void openMainLayout() { try { FXMLLoader loader = new FXMLLoader( diff --git a/src/main/java/org/example/petshopdesktop/controllers/MainLayoutController.java b/src/main/java/org/example/petshopdesktop/controllers/MainLayoutController.java index 76294154..a104c135 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/MainLayoutController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/MainLayoutController.java @@ -8,6 +8,7 @@ import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.Label; +import javafx.scene.control.Separator; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import org.example.petshopdesktop.auth.UserSession; @@ -66,12 +67,24 @@ public class MainLayoutController { @FXML private Button btnStaffAccounts; + @FXML + private Button btnAnalytics; + + @FXML + private Button btnChat; + @FXML private Label lblUsername; @FXML private Label lblRole; + @FXML + private Label lblAdminSection; + + @FXML + private Separator separatorAdmin; + @FXML private StackPane spContentArea; @@ -129,6 +142,12 @@ public class MainLayoutController { updateButtons(btnStaffAccounts); } + @FXML + void btnAnalyticsClicked(ActionEvent event) { + loadView("analytics-view.fxml"); + updateButtons(btnAnalytics); + } + @FXML void btnServicesClicked(ActionEvent event) { loadView("service-view.fxml"); @@ -141,6 +160,12 @@ public class MainLayoutController { updateButtons(btnSuppliers); } + @FXML + void btnChatClicked(ActionEvent event) { + loadView("chat-view.fxml"); + updateButtons(btnChat); + } + @FXML void btnLogoutClicked(ActionEvent event) { UserSession.getInstance().logout(); @@ -165,8 +190,8 @@ public class MainLayoutController { public void initialize() { applyRBAC(); - loadView("pet-view.fxml"); - updateButtons(btnPets); + loadView("analytics-view.fxml"); + updateButtons(btnAnalytics); } private void applyRBAC() { @@ -195,6 +220,16 @@ public class MainLayoutController { btnStaffAccounts.setManaged(isAdmin); } + if (lblAdminSection != null) { + lblAdminSection.setVisible(isAdmin); + lblAdminSection.setManaged(isAdmin); + } + + if (separatorAdmin != null) { + separatorAdmin.setVisible(isAdmin); + separatorAdmin.setManaged(isAdmin); + } + btnSalesHistory.setText(isAdmin ? "Sales History" : "Sales"); @@ -234,7 +269,9 @@ public class MainLayoutController { btnProductSuppliers, btnProducts, btnPurchaseOrders, - btnStaffAccounts + btnStaffAccounts, + btnAnalytics, + btnChat }; for (Button button : buttons) { diff --git a/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java b/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java index 8e92ddb6..6006bb15 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java @@ -5,11 +5,16 @@ import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; import javafx.event.ActionEvent; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; +import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.TextField; import javafx.scene.control.cell.PropertyValueFactory; +import javafx.stage.Modality; +import javafx.stage.Stage; import org.example.petshopdesktop.auth.UserSession; import org.example.petshopdesktop.database.UserDB; import org.example.petshopdesktop.models.StaffAccount; @@ -46,6 +51,9 @@ public class StaffAccountsController { @FXML private Label lblError; + @FXML + private Button btnCreateAccount; + private final ObservableList staffAccounts = FXCollections.observableArrayList(); private FilteredList filtered; @@ -66,6 +74,7 @@ public class StaffAccountsController { if (!UserSession.getInstance().isAdmin()) { lblError.setText("Access restricted."); tvStaff.setDisable(true); + btnCreateAccount.setDisable(true); return; } @@ -77,6 +86,25 @@ public class StaffAccountsController { refresh(); } + @FXML + void btnCreateAccountClicked(ActionEvent event) { + lblError.setText(""); + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/staff-register-dialog-view.fxml")); + Stage dialog = new Stage(); + dialog.initOwner(tvStaff.getScene().getWindow()); + dialog.initModality(Modality.APPLICATION_MODAL); + dialog.setTitle("Create Staff Account"); + dialog.setScene(new Scene(loader.load())); + dialog.setResizable(false); + dialog.showAndWait(); + refresh(); + } catch (Exception e) { + ActivityLogger.getInstance().logException("StaffAccountsController.btnCreateAccountClicked", e, "Opening staff register dialog"); + lblError.setText("Could not open staff account creation."); + } + } + private void refresh() { lblError.setText(""); try { diff --git a/src/main/java/org/example/petshopdesktop/database/SaleDB.java b/src/main/java/org/example/petshopdesktop/database/SaleDB.java index 7c8a541c..bedd6566 100644 --- a/src/main/java/org/example/petshopdesktop/database/SaleDB.java +++ b/src/main/java/org/example/petshopdesktop/database/SaleDB.java @@ -5,9 +5,11 @@ import javafx.collections.ObservableList; import org.example.petshopdesktop.DTOs.SaleDTO; import org.example.petshopdesktop.models.SaleCartItem; import org.example.petshopdesktop.models.SaleLineItem; +import org.example.petshopdesktop.models.analytics.*; import org.example.petshopdesktop.util.ActivityLogger; import java.sql.*; +import java.time.LocalDate; public class SaleDB { @@ -230,4 +232,169 @@ public class SaleDB { conn.close(); } } + + public static ObservableList getDailySalesRevenue() throws SQLException { + ObservableList dailySales = FXCollections.observableArrayList(); + Connection conn = ConnectionDB.getConnection(); + + String sql = """ + SELECT DATE(s.saleDate) as saleDate, SUM(s.totalAmount) as revenue + FROM sale s + GROUP BY DATE(s.saleDate) + ORDER BY saleDate ASC + """; + + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + + while (rs.next()) { + LocalDate date = rs.getDate("saleDate").toLocalDate(); + double revenue = rs.getDouble("revenue"); + dailySales.add(new DailySalesData(date, revenue)); + } + + conn.close(); + return dailySales; + } + + public static ObservableList getTopProductsByRevenue(int limit) throws SQLException { + ObservableList products = FXCollections.observableArrayList(); + Connection conn = ConnectionDB.getConnection(); + + String sql = """ + SELECT p.prodName, SUM(si.quantity * si.unitPrice) as totalRevenue + FROM saleItem si + JOIN product p ON si.prodId = p.prodId + GROUP BY p.prodId, p.prodName + ORDER BY totalRevenue DESC + LIMIT ? + """; + + PreparedStatement pstmt = conn.prepareStatement(sql); + pstmt.setInt(1, limit); + ResultSet rs = pstmt.executeQuery(); + + while (rs.next()) { + String productName = rs.getString("prodName"); + double totalRevenue = rs.getDouble("totalRevenue"); + products.add(new ProductSalesData(productName, 0, totalRevenue)); + } + + conn.close(); + return products; + } + + public static ObservableList getTopProductsByQuantity(int limit) throws SQLException { + ObservableList products = FXCollections.observableArrayList(); + Connection conn = ConnectionDB.getConnection(); + + String sql = """ + SELECT p.prodName, SUM(si.quantity) as totalQuantity, + SUM(si.quantity * si.unitPrice) as totalRevenue + FROM saleItem si + JOIN product p ON si.prodId = p.prodId + GROUP BY p.prodId, p.prodName + ORDER BY totalQuantity DESC + LIMIT ? + """; + + PreparedStatement pstmt = conn.prepareStatement(sql); + pstmt.setInt(1, limit); + ResultSet rs = pstmt.executeQuery(); + + while (rs.next()) { + String productName = rs.getString("prodName"); + int totalQuantity = rs.getInt("totalQuantity"); + double totalRevenue = rs.getDouble("totalRevenue"); + products.add(new ProductSalesData(productName, totalQuantity, totalRevenue)); + } + + conn.close(); + return products; + } + + public static ObservableList getPaymentMethodDistribution() throws SQLException { + ObservableList paymentMethods = FXCollections.observableArrayList(); + Connection conn = ConnectionDB.getConnection(); + + String sql = """ + SELECT s.paymentMethod, COUNT(*) as transactionCount, + SUM(s.totalAmount) as totalRevenue + FROM sale s + GROUP BY s.paymentMethod + ORDER BY totalRevenue DESC + """; + + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + + while (rs.next()) { + String paymentMethod = rs.getString("paymentMethod"); + int transactionCount = rs.getInt("transactionCount"); + double totalRevenue = rs.getDouble("totalRevenue"); + paymentMethods.add(new PaymentMethodData(paymentMethod, transactionCount, totalRevenue)); + } + + conn.close(); + return paymentMethods; + } + + public static ObservableList getEmployeeSalesPerformance() throws SQLException { + ObservableList employees = FXCollections.observableArrayList(); + Connection conn = ConnectionDB.getConnection(); + + String sql = """ + SELECT CONCAT(e.firstName, ' ', e.lastName) as employeeName, + COUNT(DISTINCT s.saleId) as transactionCount, + SUM(s.totalAmount) as totalRevenue, + COALESCE(SUM(si.quantity), 0) as totalItemsSold + FROM sale s + JOIN employee e ON s.employeeId = e.employeeId + LEFT JOIN saleItem si ON s.saleId = si.saleId + GROUP BY e.employeeId, e.firstName, e.lastName + ORDER BY totalRevenue DESC + """; + + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + + while (rs.next()) { + String employeeName = rs.getString("employeeName"); + int transactionCount = rs.getInt("transactionCount"); + double totalRevenue = rs.getDouble("totalRevenue"); + int totalItemsSold = rs.getInt("totalItemsSold"); + employees.add(new EmployeeSalesData(employeeName, transactionCount, totalRevenue, totalItemsSold)); + } + + conn.close(); + return employees; + } + + public static SalesSummary getSalesSummary() throws SQLException { + Connection conn = ConnectionDB.getConnection(); + + String sql = """ + SELECT COUNT(DISTINCT s.saleId) as totalTransactions, + COALESCE(SUM(s.totalAmount), 0) as totalRevenue, + COALESCE(AVG(s.totalAmount), 0) as avgTransactionValue, + COALESCE(SUM(si.quantity), 0) as totalItemsSold + FROM sale s + LEFT JOIN saleItem si ON s.saleId = si.saleId + """; + + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery(sql); + + SalesSummary summary = null; + if (rs.next()) { + int totalTransactions = rs.getInt("totalTransactions"); + double totalRevenue = rs.getDouble("totalRevenue"); + double avgTransactionValue = rs.getDouble("avgTransactionValue"); + int totalItemsSold = rs.getInt("totalItemsSold"); + summary = new SalesSummary(totalTransactions, totalRevenue, avgTransactionValue, totalItemsSold); + } + + conn.close(); + return summary; + } } diff --git a/src/main/java/org/example/petshopdesktop/models/analytics/DailySalesData.java b/src/main/java/org/example/petshopdesktop/models/analytics/DailySalesData.java new file mode 100644 index 00000000..1f41b8f2 --- /dev/null +++ b/src/main/java/org/example/petshopdesktop/models/analytics/DailySalesData.java @@ -0,0 +1,21 @@ +package org.example.petshopdesktop.models.analytics; + +import java.time.LocalDate; + +public class DailySalesData { + private final LocalDate date; + private final double revenue; + + public DailySalesData(LocalDate date, double revenue) { + this.date = date; + this.revenue = revenue; + } + + public LocalDate getDate() { + return date; + } + + public double getRevenue() { + return revenue; + } +} diff --git a/src/main/java/org/example/petshopdesktop/models/analytics/EmployeeSalesData.java b/src/main/java/org/example/petshopdesktop/models/analytics/EmployeeSalesData.java new file mode 100644 index 00000000..a954d86b --- /dev/null +++ b/src/main/java/org/example/petshopdesktop/models/analytics/EmployeeSalesData.java @@ -0,0 +1,31 @@ +package org.example.petshopdesktop.models.analytics; + +public class EmployeeSalesData { + private final String employeeName; + private final int transactionCount; + private final double totalRevenue; + private final int totalItemsSold; + + public EmployeeSalesData(String employeeName, int transactionCount, double totalRevenue, int totalItemsSold) { + this.employeeName = employeeName; + this.transactionCount = transactionCount; + this.totalRevenue = totalRevenue; + this.totalItemsSold = totalItemsSold; + } + + public String getEmployeeName() { + return employeeName; + } + + public int getTransactionCount() { + return transactionCount; + } + + public double getTotalRevenue() { + return totalRevenue; + } + + public int getTotalItemsSold() { + return totalItemsSold; + } +} diff --git a/src/main/java/org/example/petshopdesktop/models/analytics/PaymentMethodData.java b/src/main/java/org/example/petshopdesktop/models/analytics/PaymentMethodData.java new file mode 100644 index 00000000..de45c727 --- /dev/null +++ b/src/main/java/org/example/petshopdesktop/models/analytics/PaymentMethodData.java @@ -0,0 +1,25 @@ +package org.example.petshopdesktop.models.analytics; + +public class PaymentMethodData { + private final String paymentMethod; + private final int transactionCount; + private final double totalRevenue; + + public PaymentMethodData(String paymentMethod, int transactionCount, double totalRevenue) { + this.paymentMethod = paymentMethod; + this.transactionCount = transactionCount; + this.totalRevenue = totalRevenue; + } + + public String getPaymentMethod() { + return paymentMethod; + } + + public int getTransactionCount() { + return transactionCount; + } + + public double getTotalRevenue() { + return totalRevenue; + } +} diff --git a/src/main/java/org/example/petshopdesktop/models/analytics/ProductSalesData.java b/src/main/java/org/example/petshopdesktop/models/analytics/ProductSalesData.java new file mode 100644 index 00000000..3723eee6 --- /dev/null +++ b/src/main/java/org/example/petshopdesktop/models/analytics/ProductSalesData.java @@ -0,0 +1,25 @@ +package org.example.petshopdesktop.models.analytics; + +public class ProductSalesData { + private final String productName; + private final int totalQuantity; + private final double totalRevenue; + + public ProductSalesData(String productName, int totalQuantity, double totalRevenue) { + this.productName = productName; + this.totalQuantity = totalQuantity; + this.totalRevenue = totalRevenue; + } + + public String getProductName() { + return productName; + } + + public int getTotalQuantity() { + return totalQuantity; + } + + public double getTotalRevenue() { + return totalRevenue; + } +} diff --git a/src/main/java/org/example/petshopdesktop/models/analytics/SalesSummary.java b/src/main/java/org/example/petshopdesktop/models/analytics/SalesSummary.java new file mode 100644 index 00000000..65e9f9c1 --- /dev/null +++ b/src/main/java/org/example/petshopdesktop/models/analytics/SalesSummary.java @@ -0,0 +1,31 @@ +package org.example.petshopdesktop.models.analytics; + +public class SalesSummary { + private final int totalTransactions; + private final double totalRevenue; + private final double avgTransactionValue; + private final int totalItemsSold; + + public SalesSummary(int totalTransactions, double totalRevenue, double avgTransactionValue, int totalItemsSold) { + this.totalTransactions = totalTransactions; + this.totalRevenue = totalRevenue; + this.avgTransactionValue = avgTransactionValue; + this.totalItemsSold = totalItemsSold; + } + + public int getTotalTransactions() { + return totalTransactions; + } + + public double getTotalRevenue() { + return totalRevenue; + } + + public double getAvgTransactionValue() { + return avgTransactionValue; + } + + public int getTotalItemsSold() { + return totalItemsSold; + } +} diff --git a/src/main/resources/org/example/petshopdesktop/login-view.fxml b/src/main/resources/org/example/petshopdesktop/login-view.fxml index c15d860c..6b76dcc9 100644 --- a/src/main/resources/org/example/petshopdesktop/login-view.fxml +++ b/src/main/resources/org/example/petshopdesktop/login-view.fxml @@ -76,17 +76,5 @@ - - diff --git a/src/main/resources/org/example/petshopdesktop/main-layout-view.fxml b/src/main/resources/org/example/petshopdesktop/main-layout-view.fxml index 28f412c5..e57286ef 100644 --- a/src/main/resources/org/example/petshopdesktop/main-layout-view.fxml +++ b/src/main/resources/org/example/petshopdesktop/main-layout-view.fxml @@ -3,6 +3,7 @@ + @@ -12,152 +13,181 @@ - - - - - - - - + + + + + + + + + - + - - - - - + + + + + - + - - - - - + - + + + - + - + - - - + + + + + + + + + + + +
diff --git a/src/main/resources/org/example/petshopdesktop/modelviews/analytics-view.fxml b/src/main/resources/org/example/petshopdesktop/modelviews/analytics-view.fxml new file mode 100644 index 00000000..5aa4acb4 --- /dev/null +++ b/src/main/resources/org/example/petshopdesktop/modelviews/analytics-view.fxml @@ -0,0 +1,223 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml b/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml new file mode 100644 index 00000000..8dc85932 --- /dev/null +++ b/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/src/main/resources/org/example/petshopdesktop/modelviews/staff-accounts-view.fxml b/src/main/resources/org/example/petshopdesktop/modelviews/staff-accounts-view.fxml index 1318ad96..b2771e6f 100644 --- a/src/main/resources/org/example/petshopdesktop/modelviews/staff-accounts-view.fxml +++ b/src/main/resources/org/example/petshopdesktop/modelviews/staff-accounts-view.fxml @@ -25,6 +25,14 @@ +