diff --git a/spending.db b/spending.db index f67a8ce..938a42d 100644 Binary files a/spending.db and b/spending.db differ diff --git a/src/main/java/edu/ucsd/spendingtracker/App.java b/src/main/java/edu/ucsd/spendingtracker/App.java index 8f7e281..bfb0cfc 100644 --- a/src/main/java/edu/ucsd/spendingtracker/App.java +++ b/src/main/java/edu/ucsd/spendingtracker/App.java @@ -1,6 +1,8 @@ package edu.ucsd.spendingtracker; -import edu.ucsd.spendingtracker.datasource.InMemoryDataSource; +import java.util.ArrayList; +import java.util.List; + import edu.ucsd.spendingtracker.datasource.SqlDataSource; import edu.ucsd.spendingtracker.model.Model; import edu.ucsd.spendingtracker.presenter.PresenterManager; @@ -9,15 +11,16 @@ import edu.ucsd.spendingtracker.repository.ExpenseRepository; import edu.ucsd.spendingtracker.view.SpendingView; import edu.ucsd.spendingtracker.view.SummaryView; +import edu.ucsd.spendingtracker.view.charts.BarChartProvider; +import edu.ucsd.spendingtracker.view.charts.PieChartProvider; +import edu.ucsd.spendingtracker.view.charts.IChartProvider; import javafx.application.Application; import javafx.stage.Stage; public class App extends Application { @Override public void start(Stage primaryStage) { - // InMemoryDataSource dataSource = InMemoryDataSource.getDefaultDataSource(); SqlDataSource dataSource = new SqlDataSource(); - ExpenseRepository repository = new ExpenseRepository(dataSource); Model sharedModel = new Model(repository); @@ -25,8 +28,12 @@ public void start(Stage primaryStage) { SpendingView spendingView = new SpendingView(); SummaryView summaryView = new SummaryView(); + List chartProviders = new ArrayList<>(); + chartProviders.add(new BarChartProvider()); + chartProviders.add(new PieChartProvider()); + SpendingPresenter listPresenter = new SpendingPresenter(sharedModel, spendingView); - SummaryPresenter summaryPresenter = new SummaryPresenter(sharedModel, summaryView); + SummaryPresenter summaryPresenter = new SummaryPresenter(sharedModel, summaryView, chartProviders); PresenterManager manager = new PresenterManager(); manager.defineInteractions(primaryStage, "Spending Tracker", listPresenter, summaryPresenter); diff --git a/src/main/java/edu/ucsd/spendingtracker/presenter/SummaryPresenter.java b/src/main/java/edu/ucsd/spendingtracker/presenter/SummaryPresenter.java index ff4f4d9..2811753 100644 --- a/src/main/java/edu/ucsd/spendingtracker/presenter/SummaryPresenter.java +++ b/src/main/java/edu/ucsd/spendingtracker/presenter/SummaryPresenter.java @@ -1,18 +1,37 @@ package edu.ucsd.spendingtracker.presenter; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import edu.ucsd.spendingtracker.model.Expense; import edu.ucsd.spendingtracker.model.Model; import edu.ucsd.spendingtracker.view.SummaryView; +import edu.ucsd.spendingtracker.model.Category; +import edu.ucsd.spendingtracker.view.charts.IChartProvider; + +import javafx.scene.Node; + public class SummaryPresenter extends AbstractPresenter { private Runnable onBack; + private final List chartProviders; - public SummaryPresenter(Model model, SummaryView view) { + public SummaryPresenter(Model model, SummaryView view, List chartProviders) { super(model, view); + this.chartProviders = chartProviders; + this.view.getChartSelector().getItems().addAll(this.chartProviders); + + if(!this.chartProviders.isEmpty()) { + this.view.getChartSelector().setValue(this.chartProviders.get(0)); + } this.view.getBackButton().setOnAction(e -> { if (onBack != null) onBack.run(); }); + + this.view.getChartSelector().setOnAction(e -> updateView()); } public void setOnBack(Runnable action) { @@ -21,7 +40,28 @@ public void setOnBack(Runnable action) { @Override public void updateView() { + List expenses = model.getExpenses(); + Map totals = new TreeMap<>(); + + for (Category cat : Category.values()) { + totals.put(cat, 0.0); + } + + for (Expense expense : expenses) { + Category category = expense.getCategory(); + double amount = expense.getAmount(); + + totals.put(category, totals.get(category) + amount); + } + view.setTotal(model.getTotalSpending()); + + IChartProvider selectedProvider = view.getChartSelector().getValue(); + + if (selectedProvider != null) { + Node chartNode = selectedProvider.createChart(totals); + view.setChartDisplay(chartNode); + } } @Override diff --git a/src/main/java/edu/ucsd/spendingtracker/view/SummaryView.java b/src/main/java/edu/ucsd/spendingtracker/view/SummaryView.java index 1bf0e9c..f4b0f60 100644 --- a/src/main/java/edu/ucsd/spendingtracker/view/SummaryView.java +++ b/src/main/java/edu/ucsd/spendingtracker/view/SummaryView.java @@ -1,23 +1,57 @@ package edu.ucsd.spendingtracker.view; +import edu.ucsd.spendingtracker.view.charts.IChartProvider; import javafx.geometry.*; import javafx.scene.control.*; import javafx.scene.layout.*; +import javafx.util.StringConverter; +import javafx.scene.Node; public class SummaryView extends VBox { private Label totalLabel = new Label(); private Button backButton = new Button("Back to Expenses"); + private final ComboBox chartSelector = new ComboBox<>(); + + private final StackPane chartContainer = new StackPane(); + public SummaryView() { this.setAlignment(Pos.CENTER); this.setSpacing(20); + this.setPadding(new Insets(30)); this.setStyle("-fx-background-color: #FFFFFF;"); - Label title = new Label("Total Spending"); + Label title = new Label("Spending Analysis"); title.setStyle("-fx-font-size: 20px; -fx-font-weight: bold;"); totalLabel.setStyle("-fx-font-size: 32px; -fx-text-fill: #2E7D32;"); - this.getChildren().addAll(title, totalLabel, backButton); + chartSelector.setPromptText("Select Visualization Type"); + chartSelector.setPrefWidth(200); + + chartSelector.setConverter(new StringConverter() { + @Override + public String toString(IChartProvider provider) { + return (provider == null) ? "" : provider.getDisplayName(); + } + + @Override + public IChartProvider fromString(String string) { + return null; + } + }); + + chartContainer.setPrefSize(400, 300); + chartContainer.setStyle("-fx-border-color: #EEEEEE; -fx-border-width: 1; -fx-border-radius: 5;"); + + backButton.setStyle("-fx-background-color: #757575; -fx-text-fill: white;"); + + this.getChildren().addAll( + title, + totalLabel, + new Label("View Mode: "), + chartSelector, + chartContainer, + backButton); } public void setTotal(double total) { @@ -27,4 +61,15 @@ public void setTotal(double total) { public Button getBackButton() { return backButton; } + + public void setChartDisplay(Node chartNode) { + chartContainer.getChildren().clear(); + if(chartNode != null) { + chartContainer.getChildren().add(chartNode); + } + } + + public ComboBox getChartSelector() { + return chartSelector; + } } \ No newline at end of file diff --git a/src/main/java/edu/ucsd/spendingtracker/view/charts/BarChartProvider.java b/src/main/java/edu/ucsd/spendingtracker/view/charts/BarChartProvider.java new file mode 100644 index 0000000..da9084d --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/view/charts/BarChartProvider.java @@ -0,0 +1,41 @@ +package edu.ucsd.spendingtracker.view.charts; + +import edu.ucsd.spendingtracker.model.Category; +import javafx.scene.Node; +import javafx.scene.chart.*; + +import java.util.Map; + + +public class BarChartProvider implements IChartProvider { + @Override + public Node createChart(Map data) { + CategoryAxis xAxis = new CategoryAxis(); + NumberAxis yAxis = new NumberAxis(); + BarChart chart = new BarChart<>(xAxis, yAxis); + + XYChart.Series series = new XYChart.Series<>(); + + data.forEach((cat, sum) -> { + series.getData().add(new XYChart.Data<>(cat.name(), sum)); + }); + + chart.getData().add(series); + for (XYChart.Data entry : series.getData()) { + String color = Category.valueOf(entry.getXValue()).color; + Node bar = entry.getNode(); + if (bar != null) { + bar.setStyle("-fx-bar-fill: " + color + ";"); + } + } + + chart.setLegendVisible(false); + + return chart; + } + + @Override + public String getDisplayName() { + return "Bar Chart"; + } +} diff --git a/src/main/java/edu/ucsd/spendingtracker/view/charts/IChartProvider.java b/src/main/java/edu/ucsd/spendingtracker/view/charts/IChartProvider.java new file mode 100644 index 0000000..fe96f84 --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/view/charts/IChartProvider.java @@ -0,0 +1,11 @@ +package edu.ucsd.spendingtracker.view.charts; + +import edu.ucsd.spendingtracker.model.Category; +import javafx.scene.Node; +import java.util.Map; + +public interface IChartProvider { + Node createChart(Map data); + + String getDisplayName(); +} diff --git a/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java b/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java new file mode 100644 index 0000000..74456e7 --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java @@ -0,0 +1,40 @@ +package edu.ucsd.spendingtracker.view.charts; + +import edu.ucsd.spendingtracker.model.Category; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.scene.chart.PieChart; +import javafx.scene.Node; +import java.util.Map; + +public class PieChartProvider implements IChartProvider { + @Override + public Node createChart(Map data) { + ObservableList chartData = FXCollections.observableArrayList(); + + data.forEach((cat, sum) -> { + chartData.add(new PieChart.Data(cat.name(), sum)); + }); + + PieChart chart = new PieChart(chartData); + + for (PieChart.Data entry : chartData) { + String color = Category.valueOf(entry.getName()).color; + System.out.println(entry.getName()); + Node slice = entry.getNode(); + if (slice != null) { + slice.setStyle("-fx-pie-color: " + color + ";"); + } + } + + chart.setLegendVisible(false); + + return chart; + } + + @Override + public String getDisplayName() { + return "Pie Chart"; + } + +} diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index e85b8df..fa08e51 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -2,6 +2,7 @@ requires javafx.controls; requires javafx.fxml; requires java.sql; + requires javafx.base; opens edu.ucsd.spendingtracker to javafx.fxml; exports edu.ucsd.spendingtracker; diff --git a/target/classes/edu/ucsd/spendingtracker/App.class b/target/classes/edu/ucsd/spendingtracker/App.class index dd6d8f7..7645885 100644 Binary files a/target/classes/edu/ucsd/spendingtracker/App.class and b/target/classes/edu/ucsd/spendingtracker/App.class differ diff --git a/target/classes/edu/ucsd/spendingtracker/presenter/SummaryPresenter.class b/target/classes/edu/ucsd/spendingtracker/presenter/SummaryPresenter.class index 0e808ca..9143c51 100644 Binary files a/target/classes/edu/ucsd/spendingtracker/presenter/SummaryPresenter.class and b/target/classes/edu/ucsd/spendingtracker/presenter/SummaryPresenter.class differ diff --git a/target/classes/edu/ucsd/spendingtracker/view/SummaryView$1.class b/target/classes/edu/ucsd/spendingtracker/view/SummaryView$1.class new file mode 100644 index 0000000..18dc59d Binary files /dev/null and b/target/classes/edu/ucsd/spendingtracker/view/SummaryView$1.class differ diff --git a/target/classes/edu/ucsd/spendingtracker/view/SummaryView.class b/target/classes/edu/ucsd/spendingtracker/view/SummaryView.class index c8a5ba9..82c2c04 100644 Binary files a/target/classes/edu/ucsd/spendingtracker/view/SummaryView.class and b/target/classes/edu/ucsd/spendingtracker/view/SummaryView.class differ diff --git a/target/classes/edu/ucsd/spendingtracker/view/charts/BarChartProvider.class b/target/classes/edu/ucsd/spendingtracker/view/charts/BarChartProvider.class new file mode 100644 index 0000000..264ef81 Binary files /dev/null and b/target/classes/edu/ucsd/spendingtracker/view/charts/BarChartProvider.class differ diff --git a/target/classes/edu/ucsd/spendingtracker/view/charts/IChartProvider.class b/target/classes/edu/ucsd/spendingtracker/view/charts/IChartProvider.class new file mode 100644 index 0000000..27dc553 Binary files /dev/null and b/target/classes/edu/ucsd/spendingtracker/view/charts/IChartProvider.class differ diff --git a/target/classes/edu/ucsd/spendingtracker/view/charts/PieChartProvider.class b/target/classes/edu/ucsd/spendingtracker/view/charts/PieChartProvider.class new file mode 100644 index 0000000..1e6e583 Binary files /dev/null and b/target/classes/edu/ucsd/spendingtracker/view/charts/PieChartProvider.class differ diff --git a/target/classes/module-info.class b/target/classes/module-info.class index f7e553d..56c5db1 100644 Binary files a/target/classes/module-info.class and b/target/classes/module-info.class differ diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst index a8ce4f0..e903b9d 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst @@ -2,7 +2,11 @@ edu/ucsd/spendingtracker/view/SummaryView.class edu/ucsd/spendingtracker/presenter/SpendingPresenter.class edu/ucsd/spendingtracker/model/Model.class edu/ucsd/spendingtracker/presenter/SummaryPresenter.class +edu/ucsd/spendingtracker/view/charts/PieChartProvider.class edu/ucsd/spendingtracker/App.class +edu/ucsd/spendingtracker/view/charts/IChartProvider.class +edu/ucsd/spendingtracker/view/charts/BarChartProvider.class +edu/ucsd/spendingtracker/view/SummaryView$1.class module-info.class edu/ucsd/spendingtracker/repository/ExpenseRepository.class edu/ucsd/spendingtracker/datasource/IDataSource.class diff --git a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst index 3b467f5..2524f5e 100644 --- a/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst +++ b/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst @@ -13,4 +13,7 @@ /Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java /Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java /Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/view/SummaryView.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/view/charts/BarChartProvider.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/view/charts/IChartProvider.java +/Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java /Users/rickyzam/Documents/UCSD/CSE110/CSE110-Lab4/src/main/java/module-info.java