From a1f627b731d1f7b968321fa6da690811a42dea9f Mon Sep 17 00:00:00 2001 From: areddot Date: Thu, 29 Jan 2026 13:36:13 -0800 Subject: [PATCH 1/4] database and UI changed --- spending.db | Bin 0 -> 12288 bytes .../java/edu/ucsd/spendingtracker/.DS_Store | Bin 0 -> 6148 bytes .../java/edu/ucsd/spendingtracker/App.java | 4 +- .../datasource/IDataSource.java | 12 +++ .../datasource/InMemoryDataSource.java | 19 ++-- .../datasource/SqlDataSource.java | 66 +++++++++++++ .../ucsd/spendingtracker/model/Expense.java | 8 +- .../edu/ucsd/spendingtracker/model/Model.java | 4 + .../presenter/SpendingPresenter.java | 16 ++- .../repository/ExpenseRepository.java | 10 +- .../spendingtracker/view/SpendingView.java | 92 +++++++++++++++++- .../edu/ucsd/spendingtracker/.DS_Store | Bin 0 -> 6148 bytes .../edu/ucsd/spendingtracker/App.class | Bin 2399 -> 2295 bytes .../datasource/IDataSource.class | Bin 0 -> 363 bytes .../datasource/InMemoryDataSource.class | Bin 1847 -> 2026 bytes .../datasource/SqlDataSource.class | Bin 0 -> 4155 bytes .../ucsd/spendingtracker/model/Expense.class | Bin 879 -> 1002 bytes .../ucsd/spendingtracker/model/Model.class | Bin 1031 -> 1152 bytes .../presenter/SpendingPresenter.class | Bin 3055 -> 4458 bytes .../repository/ExpenseRepository.class | Bin 1408 -> 1516 bytes .../spendingtracker/view/SpendingView.class | Bin 3769 -> 8013 bytes 21 files changed, 207 insertions(+), 24 deletions(-) create mode 100644 spending.db create mode 100644 src/main/java/edu/ucsd/spendingtracker/.DS_Store create mode 100644 src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java create mode 100644 src/main/java/edu/ucsd/spendingtracker/datasource/SqlDataSource.java create mode 100644 target/classes/edu/ucsd/spendingtracker/.DS_Store create mode 100644 target/classes/edu/ucsd/spendingtracker/datasource/IDataSource.class create mode 100644 target/classes/edu/ucsd/spendingtracker/datasource/SqlDataSource.class diff --git a/spending.db b/spending.db new file mode 100644 index 0000000000000000000000000000000000000000..ed00d5db432162d8e97747a83b8cbb7c3cd8a7c3 GIT binary patch literal 12288 zcmeI&K~KUk6bJBj0}Y90TnzEB_zosQARhD!IJKHZ7&vAkCo`c61ctCd^x%P`pU!XM z!B60uVF$T*HRk`)uI8BKTu0sYp?T&jCr}hPr*%bZbIVaU)-_&PSqiyXvTeC+fA6WEpL7)KIBSg`yJT;v zJm`_@1?p1y)bibi<9Fyvb;!91ny$xd8p;c5lzxQ*b<5punCQpJ>}53!$CG)K5FfE# zNpo{f`i1pjz5i`~oDKpIfB*y_009U<00Izz00bZaft7%r%Zt4OBk2!f;&Q|{0m=^? z*GumNjQygS7rQ%h*zYa6!;5C~yp-nu()tu!5D1Rwwb2tWV=5P$##AOHaf{2PHS LY1%UTnIQKC+lXM1 literal 0 HcmV?d00001 diff --git a/src/main/java/edu/ucsd/spendingtracker/.DS_Store b/src/main/java/edu/ucsd/spendingtracker/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6feb894a50a23614d266d16d0fc2c1b45dae5054 GIT binary patch literal 6148 zcmeHKJ5EDE3>=db5i}_&_X^x#6@?Sz0w98DP$C6F{i>XcqcQ#{B6>-Yf(DHxdv?8^ zeR@+oKLfDEe*FN<0nF%*ICvPFpSzFjrZPsP^NtT}vBwTCcpX)rPdN7$YdqtV{)_*$ z+HKyqo436CJXu*OAO)m=6p#W^;A#cD_tIu}iHcG{3P^#Y0{(qybjMyeB*v$MAw~e= zl<6?8W0oK`PY`?IkjMd96UipA4;e~WThPgIlw zQs7j9Np9!f{~zfW=KoWYc2YnJ{3``)x?C+6e5LBGqnGnu+vrbpulc6CaUB$fXvf58 i$J}^3zK^1;Yrf`rFB}qs&V0~``WbLtWK!U-75D*pjuox| literal 0 HcmV?d00001 diff --git a/src/main/java/edu/ucsd/spendingtracker/App.java b/src/main/java/edu/ucsd/spendingtracker/App.java index 7d2f29b..8f4a7f3 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.IDataSource; import edu.ucsd.spendingtracker.datasource.InMemoryDataSource; +import edu.ucsd.spendingtracker.datasource.SqlDataSource; import edu.ucsd.spendingtracker.model.Model; import edu.ucsd.spendingtracker.presenter.PresenterManager; import edu.ucsd.spendingtracker.presenter.SpendingPresenter; @@ -14,7 +16,7 @@ public class App extends Application { @Override public void start(Stage primaryStage) { - InMemoryDataSource dataSource = InMemoryDataSource.getDefaultDataSource(); + IDataSource dataSource = new SqlDataSource(); ExpenseRepository repository = new ExpenseRepository(dataSource); Model sharedModel = new Model(repository); diff --git a/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java b/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java new file mode 100644 index 0000000..07fa1f5 --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/datasource/IDataSource.java @@ -0,0 +1,12 @@ +package edu.ucsd.spendingtracker.datasource; +import java.util.List; +import edu.ucsd.spendingtracker.model.Expense; + +public interface IDataSource { + List getExpenses(); + + void addExpense(Expense expense); + + void deleteExpense(int id); + +} diff --git a/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java b/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java index c71abcd..8c9e24c 100644 --- a/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java +++ b/src/main/java/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.java @@ -6,29 +6,22 @@ import edu.ucsd.spendingtracker.model.Category; import edu.ucsd.spendingtracker.model.Expense; -public class InMemoryDataSource { +public class InMemoryDataSource implements IDataSource { private List expenses = new ArrayList<>(); - public InMemoryDataSource() { - } - + @Override public List getExpenses() { return List.copyOf(expenses); } + @Override public void addExpense(Expense expense) { expenses.add(expense); } - public final static List DEFAULT_EXPENSES = List.of( - new Expense("Groceries", Category.FOOD, 150.75), - new Expense("Utilities", Category.UTILITIES, 80.50), - new Expense("Gas", Category.TRANSPORT, 60.00)); - - public static InMemoryDataSource getDefaultDataSource() { - InMemoryDataSource dataSource = new InMemoryDataSource(); - dataSource.expenses.addAll(DEFAULT_EXPENSES); - return dataSource; + @Override + public void deleteExpense(int expenseId){ + expenses.removeIf(expense -> expense.getId() == expenseId); } } diff --git a/src/main/java/edu/ucsd/spendingtracker/datasource/SqlDataSource.java b/src/main/java/edu/ucsd/spendingtracker/datasource/SqlDataSource.java new file mode 100644 index 0000000..b1b82ee --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/datasource/SqlDataSource.java @@ -0,0 +1,66 @@ +package edu.ucsd.spendingtracker.datasource; + + +import edu.ucsd.spendingtracker.model.*; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + + +public class SqlDataSource implements IDataSource { + private final String url = "jdbc:sqlite:spending.db"; + + + public SqlDataSource() { + try (Connection conn = DriverManager.getConnection(url)) { + conn.createStatement().execute( + "CREATE TABLE IF NOT EXISTS expenses (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, category TEXT, amount REAL)"); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + + @Override + public List getExpenses() { + List list = new ArrayList<>(); + try (Connection conn = DriverManager.getConnection(url); + ResultSet rs = conn.createStatement().executeQuery("SELECT * FROM expenses")) { + while (rs.next()) { + list.add(new Expense(rs.getInt("id"), rs.getString("name"), + Category.valueOf(rs.getString("category")), rs.getDouble("amount"))); + } + } catch (SQLException e) { + e.printStackTrace(); + } + return list; + } + + + @Override + public void addExpense(Expense e) { + try (Connection conn = DriverManager.getConnection(url); + PreparedStatement ps = conn.prepareStatement("INSERT INTO expenses(name, category, amount) VALUES(?,?,?)")) { + ps.setString(1, e.getName()); + ps.setString(2, e.getCategory().name()); + ps.setDouble(3, e.getAmount()); + ps.executeUpdate(); + } catch (SQLException err) { + err.printStackTrace(); + } + } + + + @Override + public void deleteExpense(int id) { + try (Connection conn = DriverManager.getConnection(url); + PreparedStatement ps = conn.prepareStatement("DELETE FROM expenses WHERE id = ?")) { + ps.setInt(1, id); + ps.executeUpdate(); + } catch (SQLException e) { + e.printStackTrace(); + } + } +} + + diff --git a/src/main/java/edu/ucsd/spendingtracker/model/Expense.java b/src/main/java/edu/ucsd/spendingtracker/model/Expense.java index 3b73dca..181b1b6 100644 --- a/src/main/java/edu/ucsd/spendingtracker/model/Expense.java +++ b/src/main/java/edu/ucsd/spendingtracker/model/Expense.java @@ -4,11 +4,13 @@ public class Expense { private String name; private Category category; private double amount; + private int id; - public Expense(String name, Category category, double amount) { + public Expense(int id, String name, Category category, double amount) { this.name = name; this.category = category; this.amount = amount; + this.id = id; } public String getName() { @@ -22,6 +24,10 @@ public Category getCategory() { public double getAmount() { return amount; } + + public int getId(){ + return id; + } } diff --git a/src/main/java/edu/ucsd/spendingtracker/model/Model.java b/src/main/java/edu/ucsd/spendingtracker/model/Model.java index 97e5c80..0f4c2bc 100644 --- a/src/main/java/edu/ucsd/spendingtracker/model/Model.java +++ b/src/main/java/edu/ucsd/spendingtracker/model/Model.java @@ -21,4 +21,8 @@ public List getExpenses() { public double getTotalSpending() { return repository.getTotal(); } + + public void deleteExpense(int id){ + repository.deleteExpense(id); + } } \ No newline at end of file diff --git a/src/main/java/edu/ucsd/spendingtracker/presenter/SpendingPresenter.java b/src/main/java/edu/ucsd/spendingtracker/presenter/SpendingPresenter.java index 171568d..1090995 100644 --- a/src/main/java/edu/ucsd/spendingtracker/presenter/SpendingPresenter.java +++ b/src/main/java/edu/ucsd/spendingtracker/presenter/SpendingPresenter.java @@ -14,6 +14,18 @@ public SpendingPresenter(Model model, SpendingView view) { onShowSummary.run(); }); + this.view.setOnDelete(id -> { + model.deleteExpense(id); + updateView(); + }); + + this.view.getOpenModalButton().setOnAction(e -> { + view.showAddExpenseModal(newExpense -> { + model.addExpense(newExpense); + updateView(); + }); + }); + updateView(); } @@ -27,9 +39,9 @@ public String getViewTitle() { } public void updateView() { - int i = 1; + view.clearList(); for (Expense e : model.getExpenses()) { - view.addExpenseRow(i++, e.getName(), e.getCategory().name(), + view.addExpenseRow(e.getId(), e.getName(), e.getCategory().name(), e.getCategory().color, e.getAmount()); } } diff --git a/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java b/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java index 91f5f8e..18c590c 100644 --- a/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java +++ b/src/main/java/edu/ucsd/spendingtracker/repository/ExpenseRepository.java @@ -1,13 +1,15 @@ package edu.ucsd.spendingtracker.repository; import java.util.List; + +import edu.ucsd.spendingtracker.datasource.IDataSource; import edu.ucsd.spendingtracker.datasource.InMemoryDataSource; import edu.ucsd.spendingtracker.model.Expense; public class ExpenseRepository { - private final InMemoryDataSource dataSource; + private IDataSource dataSource; - public ExpenseRepository(InMemoryDataSource dataSource) { + public ExpenseRepository(IDataSource dataSource) { this.dataSource = dataSource; } @@ -26,5 +28,9 @@ public double getTotal() { } return total; } + + public void deleteExpense(int id){ + dataSource.deleteExpense(id); + } } diff --git a/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java b/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java index b9dab5f..f458cba 100644 --- a/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java +++ b/src/main/java/edu/ucsd/spendingtracker/view/SpendingView.java @@ -1,23 +1,43 @@ package edu.ucsd.spendingtracker.view; import javafx.geometry.*; +import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.*; import javafx.scene.text.*; +import javafx.stage.Modality; +import javafx.stage.Stage; +import java.util.function.Consumer; + +import edu.ucsd.spendingtracker.model.Category; +import edu.ucsd.spendingtracker.model.Expense; + public class SpendingView extends BorderPane { private VBox listContainer; private Button summaryButton; + private Button openAddModalBtn; + private Consumer onDeleteHandler; public SpendingView() { - VBox headerBox = new VBox(10); + VBox headerBox = new VBox(15); headerBox.setAlignment(Pos.CENTER); headerBox.setPadding(new Insets(20)); Text title = new Text("Spending Tracker"); - title.setStyle("-fx-font-weight: bold; -fx-font-size: 24;"); + title.setStyle("-fx-font-weight: bold; -fx-font-size: 26;"); + + HBox navBox = new HBox(10); + navBox.setAlignment(Pos.CENTER); + summaryButton = new Button("View Summary"); - headerBox.getChildren().addAll(title, summaryButton); + openAddModalBtn = new Button("Add New Expense +"); + openAddModalBtn.setStyle("-fx-background-color: #2E7D32; -fx-text-fill: white; -fx-font-weight: bold;"); + + navBox.getChildren().addAll(openAddModalBtn, summaryButton); + headerBox.getChildren().addAll(title, navBox); + + listContainer = new VBox(5); ScrollPane scroller = new ScrollPane(listContainer); @@ -30,7 +50,7 @@ public SpendingView() { this.setStyle("-fx-background-color: #FFFFFF;"); } - public void addExpenseRow(int idx, String name, String catName, String color, double amount) { + public void addExpenseRow(int id, String name, String catName, String color, double amount) { HBox row = new HBox(10); row.setPrefSize(450, 40); row.setPadding(new Insets(5, 10, 5, 10)); @@ -47,12 +67,74 @@ public void addExpenseRow(int idx, String name, String catName, String color, do Label amtL = new Label("$" + String.format("%.2f", amount)); amtL.setPrefWidth(80); amtL.setAlignment(Pos.CENTER_RIGHT); + Button deleteBtn = new Button("X"); + + deleteBtn.setStyle("-fx-background-color: #ff6961; -fx-text-fill: white;"); + deleteBtn.setOnAction(e -> { + if (onDeleteHandler != null) onDeleteHandler.accept(id); + }); - row.getChildren().addAll(new Label(idx + "."), nameL, catL, amtL); + + + row.getChildren().addAll(nameL, catL, amtL, deleteBtn); listContainer.getChildren().add(row); } public Button getSummaryButton() { return summaryButton; } + + + public void showAddExpenseModal(Consumer onSave){ + Stage modal = new Stage(); + + modal.initModality(Modality.APPLICATION_MODAL); + // Blocks the main window + modal.setTitle("Add New Expense"); + + + VBox layout = new VBox(15); + layout.setPadding(new Insets(20)); + layout.setAlignment(Pos.CENTER); + + + TextField nameField = new TextField(); + nameField.setPromptText("Expense Name"); + TextField amountField = new TextField(); + amountField.setPromptText("Amount"); + ComboBox categoryBox = new ComboBox<>(); + categoryBox.getItems().setAll(Category.values()); + + + Button saveBtn = new Button("Save Expense"); + saveBtn.setOnAction(e -> { + try { + double amount = Double.parseDouble(amountField.getText()); + onSave.accept(new Expense( 1, nameField.getText(), categoryBox.getValue(), amount)); //! have added an arbitrary number for it to work. + modal.close(); + } catch (NumberFormatException ex) { + amountField.setStyle("-fx-border-color: red;"); + } + }); + + + layout.getChildren().addAll(new Label("Expense Details"), nameField, amountField, categoryBox, saveBtn); + modal.setScene(new Scene(layout, 300, 250)); + modal.showAndWait(); + } + + public void clearList() { + listContainer.getChildren().clear(); + } + + + public void setOnDelete(Consumer handler) { + this.onDeleteHandler = handler; + } + + + public Button getOpenModalButton() { + return openAddModalBtn; + } + } diff --git a/target/classes/edu/ucsd/spendingtracker/.DS_Store b/target/classes/edu/ucsd/spendingtracker/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6feb894a50a23614d266d16d0fc2c1b45dae5054 GIT binary patch literal 6148 zcmeHKJ5EDE3>=db5i}_&_X^x#6@?Sz0w98DP$C6F{i>XcqcQ#{B6>-Yf(DHxdv?8^ zeR@+oKLfDEe*FN<0nF%*ICvPFpSzFjrZPsP^NtT}vBwTCcpX)rPdN7$YdqtV{)_*$ z+HKyqo436CJXu*OAO)m=6p#W^;A#cD_tIu}iHcG{3P^#Y0{(qybjMyeB*v$MAw~e= zl<6?8W0oK`PY`?IkjMd96UipA4;e~WThPgIlw zQs7j9Np9!f{~zfW=KoWYc2YnJ{3``)x?C+6e5LBGqnGnu+vrbpulc6CaUB$fXvf58 i$J}^3zK^1;Yrf`rFB}qs&V0~``WbLtWK!U-75D*pjuox| literal 0 HcmV?d00001 diff --git a/target/classes/edu/ucsd/spendingtracker/App.class b/target/classes/edu/ucsd/spendingtracker/App.class index ad685f9990d31c62c723e7896a3b6d2a489bd416..cfbf1cd2c3e49f325d8d39ebbaea1109feab1028 100644 GIT binary patch delta 680 zcmYk4+fEZ<6otRPokKevvC~rQKntx!Yzw1BP+?H0`U>Z zTzlao7!ymJ#CyH*4Lm%BR~q*WO(2u()2yt$_R9Y=_s7Y8`}g?^aE<#W2}LP*tK7ZD zzG31hCZjI+p)!TF7h4M(+Z$`oU%!0%%pyzLq(9hEzMW^lM(2cLy1w^*P|$Yv5IWa* zXyOJc(XfjQMZl86kAdw(RU1|`;~h_uPR61f(N-0W-pmNTChT-2nvM#8JoPjy_^vs9 z7B$8q!qbZNn6RA41izBiU^AIjjlj{yf_KTBU1vN(O(-55LABHwLChE)>6DzgsufZm zQ#R9_54N=5YO;6A$2a<4W!$y7$5OCkZtrHvh+Q^HqAvNEWJMpxC7M#|GPPv(I3(NY zl3NbRcP6?NRziv$ugjpXg_Pyjh_8oKq&VptA+?UHxq6pVz8O-F8ly|oPlb2_IqRq0 z^mwl2?wW4u6X!n2hD5xl8OJ;+`f(Uwh$5r7cvAV4SY((sBRrxKE8jd&*HbP!xxhuy zo?@LDW`)&}TYct83d40SaT!e*XSu>W`YR!BaaG=nA)uN7Zphh-vUq`;LedsPZb_e( k?>0*ZrZ6QrHmteNokQ)GY(q#Q{-drgvl6?y8eiG|53XKo3jhEB delta 733 zcmZXRO-~b16o#MMujx#u*j6Y``DppHg<=s9VX7ipzbUAIu{#?q#Hc`;vT%hv*JQSC z{0YXy5-0Hon7C$X{1vV+o+*tim`U!r=bq<%&$+pO;=dBckH6o(1B7!-|{} z^QE1SenajsTbZ?bb>nrd?v-Xut}^Fnf!}JbeM7B% z!!PH8$11dJvci&+&>E`4`Jkoum2@=ZB`Sx+$}Y)DzR87Um!8T*lRi7(lBqNqw1X}~ zvKg^ME~6DIUEnrMOS8gXx$;@eeXSN_tu;=71W|d- zZj$V0B;>G|CB4X3i2q<~ SHuD7HF;C=N@l;kHtN#FxXoCy@ diff --git a/target/classes/edu/ucsd/spendingtracker/datasource/IDataSource.class b/target/classes/edu/ucsd/spendingtracker/datasource/IDataSource.class new file mode 100644 index 0000000000000000000000000000000000000000..b287edecf978a4626a992682f8433383671cd2e4 GIT binary patch literal 363 zcma)2TS@~#5UfsOHrebXY<1Ycqp-V6GV_e z{<`{6T~%M-AD;kjaFL)#V6l;7;Vt`DsjaKa(3s*`8nz}Fzl}{Hyt>tT-PH*Ogz3h- z8LmuS^25_cia?l@67JrW!iy)&vU%R^#NaBx-|IoPYTN0~-o2|--Sm&)tJcSmKKMj;-CIA2c literal 0 HcmV?d00001 diff --git a/target/classes/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.class b/target/classes/edu/ucsd/spendingtracker/datasource/InMemoryDataSource.class index 6c7de2fbd3ca23b7d428524b4e0df2d3b2162f2e..8cb9b52c859a415286f2bd9b0a1408728a203777 100644 GIT binary patch literal 2026 zcmbVNTT|Os5dMyB5C~zLO96EvFbs!3|srQ@14CzKV2-nz5laoG+8!=0~=XKVW=Yx=fu%?B}ZWsZQl zXC2Rxa}3#1d4(ZYB@Z206b$si&@jL-)X9E72>7<5preRFFBpamXy{=m)ErMdYd6DX%Cp z=M7xIBwY}JFdRv;rUX_guQF(fT!`0U;Tif#4MK_?YPphCUKyl8xMW}kCdomHP%?~@ zJyq;_+lxvyp9jKr8eEEsB6`KZRa_(G1~eC2!lE9Hr+c(Vm}1_WFt?~WW>L7yn`<_o zxXf^|WF5Ac@~Vy>P|!Lf-%(v?=Z z>((98N1+?@MNI0nF`gQ@iCbiN@=dd_TErrQVR@bisxA*{GirFjaDG>N_iB=cI>V`h zU1_%Cj$)i>X6e&KpN!gX^z5av$Uu*5v>D0LPnP+}4=7H(M}F#W6n}k>!M7OtGx9z{ z-+A%?Mdv8CK+h3+Q_&QIqZp+p!x)YccAVjOgnN~&%BN@QFAROai9hIf1`4k`vgcDc zJv%sOagI(EuLbhX(9=-y(;qRB!7m+7dUQ5K8-6Hs%p9L2AMa>QT?(+Q%LAPy+R zZR3V=35y9oPX}#|^Net^|<4RukC#^gG->_6Az+H{`Ov6ZLGW+|g9I q`GnjY`E(&;+*5b;BfVsBkN&~q?mi})g&Lk=i7ZNX&+!wMG4?;_VF%9u literal 1847 zcmb7Ee^V1z6g@9uvI#371}Iq3cC03#uD^FBWV35@8=a=nc_G_P ztKITkv+-QIM$`1nj?;A;(kQm?%1y`J%F|W#T`>#@j65@6nucw*TSjH$nQV9hntVl= zj_mNX^JT& znVxL1JUYfO&cw@=N?suSEkPfyWul84@7WR{fg_mGaU4GiM6;oqo2j5uex0kH%NAu0 z44qHcHB3|1I@@4*p{!Fneo{>1>$PI3SSuE)(Z$*+pMr*8Silw2mw#4A%8#q9<;vC7 z%33YDSoXs(h;z6Q!+C+BPur}+z(s+G^F-kGUh2V!WcG;Z>q&n$8<{u+F6)RRDllBK z+Opi;+>ma~+^{)Hqa~+d+I7>ll$-x+|3mofl%(EU)-;*1jll)CB1M=2{fA8r$ZpS&-opLuZn(4#}YVR(T4M4tHL6u!Xo>N zw&d707twOsnJ*+yn9XL$Phd9HU+AYBm#(YCw{;ZpJBNcH0%KojZTgWwEPMdS>!9!g zN!BedpO{_S>pd}iB3P@wtM~O@B-qzE#rmF(HSl?el6B6u1t$BIi{ujuG1V5H7 zHDVL{pTG-hrnpC}2v;J)KTZ*?m~UyARO7nGJ`9ZuK1h$wh$b!dxw?xZ4@ZZ$aWsjE z9ZdS>iEW%r;^z1~`zB2DuRX8**c*Sr_O6@HI1C-4J?nQa+1gOTdYKIzsD)zpCzec%*PoI zVnZCo?+!{tisLTIA!3m+D)YoH1VvWvDCBKidW%(J&-4fef={p&(}X|yk*G%bwNUUn Ifg-5?4_cwa1ONa4 diff --git a/target/classes/edu/ucsd/spendingtracker/datasource/SqlDataSource.class b/target/classes/edu/ucsd/spendingtracker/datasource/SqlDataSource.class new file mode 100644 index 0000000000000000000000000000000000000000..e7333e654055c64d7f1c81a484d188748e84c205 GIT binary patch literal 4155 zcmc&$`*Rc575=U)du3^{i2)OX151*EWXTpTG)-*+7+WNYB^e~y*hx#XmNrHpOJcQh z?7rLdk1FwAgPxAbzcVrGnR>SBI^ zR?4;%xCOSJ*O&BgUN0Qa8B0NjK=?tNMVqb!+A3yVpeNRJm$FPIF)FZSyjUn( zdcm5}^A*DbpTN%Z+4;;!`C>k286)+4hqChm9Y=D7oOP5A{ec+)_joaDc+rNfDpYLg z1Y@XB;PGNRdKK&t=(R)AS9rqAEg5E9FX#(~sbVJ{X7B~WV*CPkmMazn0{**G4Ah3C zi{{i(A9kT%!ES+VjR?)xDjvZef$ofH=$4VP__JsfET-dcan~3h^*|H2IG&7*r6XE; z>_jZ0MNevpsk9cEji%Bm%~&RFWuvV5b6G8#NJpNIB(+n?XnZU=r%guYw6W>*R5U>k z@kk;a(hB;bp`|0Ue9SQTLeX4tOntFfDOegq#R5J&ipLc^M%WsgXe6cLL)b5%7|TYc zVi^KEHUsB534~uo09ypwGx=hfgak3DAXJCOmQVVeS$s*K&l@U+5GL|^Hk+!HN~TdR z8(D#eTb(y1j|OJE7{(z5A7=b!j;CXh<&061q^US8LwA>`CyU8vE~Ke!rrRCM6^uk> zao#Y~GO*NNF{9^abTcPyXV7h(%asKV#U4b|8!Ck2b!R9ZX11wB1O$WbY`#miq%D!=s86(rgbzFe=MzQ>jKh zkUc||hIBToVh+y{Q!c6{%bf1L16#$;rabt#fTvzqUYx}X3O*@t;67U#cS=!(4t6tT zNw&PH7X_Z$H0}d>WA|VIb<_%5?(9Vs3piKX*+j8oYkyNjCcK!$dD%NJ2psoE?{0qg zQ&fFNqZ5G{9~Mzmzil1>X?Zb#I3%F5{aN zUAb9Ky_-o&w)9DSTg7Ww6_8D@E+UC%;C_JCCo})EcwNN|UXlL3r{eqgK~3{x_7P_* zXhNp`hKe8I$FY#4?8t^?G_>UQN2N%9C$MjVotGa18~Uzx=9x$`qVf2DN;@X=x~k&$_yY@{ zfZI)vTcQV^I#H^$_7Qh7XPo&ME5|C_s@7p#6-Nu`wq4x2CL|!gS}PkbK%V3Ega^^0f8$B#%Oictl(Na z_;+|hu`AdT47~|YFmwY0!L?ZM1`b|l9@}}Sgc+j?M|gobBzX<<%|~eMw=?Tv7Cye| z=IpJkg@@43`=iW0g>5*49e9FsHLhW<_$Z#_eLL5F3?m#%arG#Dv)6Jw3}u}^ZUsU? z(Eh*6e!LCu7|qVkbJcKohZyh0 zH1E&THmJ4t$9w*SX&VU^@kBbc|6`m$IJWKmFRFSX=y$xTJSyyd=WY{M6v-li6N>VQ|q9pa& z1~Pj-U&R+CkA3ZKYW6Ete7%hnw)6R0H}D?#Ao9 zH7t2q-N?&to4o9<;w?$a{|EU4HeNo50XLR-$$zi%sw2OLeHQFXK4RBPrSB!02Z-2Z zBK8{Fi|k*u>R4?czKR6?Xd|9$AU^0Iewm2No>oKrs6_k;8*$3oX=(}&3Tb^n9W-0q K+l=qRwf_KE0rcNO5NO!2P*&)=jS7|&+OknaO`*1pI&6WJZWPO-eB77mNzfnZ^^-6d^@21~=OSrl zr_n^fxooz=VQyX-%Irw{*>K#8OA6FU`0td!Lz1p;Yn9sl!ddQ1Z!Kmzw3jCuTsuzk zG?cF+wUAv5^+Y`@?r`}M{}~g8@`uP!?&wHwbfhzk7MaVq#_tMGpQuvow)X?8-lHit zyvI{Cy)AQ!O>cXO);F!)RvgW&vPX@6*IC0xgSA>jH+cV)wH0dzHyIUD9fd|}CPO1N zm727z-i);bZsB$@jnAm~miHYSUkMDT#$}yc(@p*rw2CHzi{D)!ZqAFF3&p#*HxnDP d&YNH6I=2>z?_+N!J|DaFc}~2uQ2ao%oWD@{w`l+X delta 409 zcmZvXJ#NB45QX2`V8C7=#Qgsz(7+}V7eFK_a{=yvgsA8_1M(H<0SOCi_p9uHxM0hH{9y9Ady0W{At|ijX@mBv20+k^5 diff --git a/target/classes/edu/ucsd/spendingtracker/model/Model.class b/target/classes/edu/ucsd/spendingtracker/model/Model.class index dee4092281371b88864c4c2b3e5b9026e279b406..0906d8001f2da5ae5b7458d07a9ce85b3f9d60ed 100644 GIT binary patch delta 166 zcmZqYXy6n$^>5cc1_lO420eBLCPoI8$%%~e8}-YXGgBt4AKk&K)x76A%h@;5ReDd!l1>V4K#+4K?lfVV$cNui-Q-M delta 46 zcmZqRZ08U-^>5cc1_lO41`T!wCPoI8$%%~e8}-YXCSPFEW@Op?hsl7Em4ShYK^*`o CP74wM diff --git a/target/classes/edu/ucsd/spendingtracker/presenter/SpendingPresenter.class b/target/classes/edu/ucsd/spendingtracker/presenter/SpendingPresenter.class index 1efeb89622f12d83bc9f81704507402f70e1e273..00cb9fd2f64d24498155d674b06801ace91642b3 100644 GIT binary patch literal 4458 zcmb_e`F9&v8NE+(J+}ND%S!4rNt33*O>Nn!8d?feCe*PLB9N2DN(F>mX@W3mL1Bzl(JJGQHg;PwgNrFyH_q4D}_XNhVL*iyk2qaexH}vCC&vhMJ;I^shPH82_ zc59B62@Yga4E-$dhRQgB_>@Yz zvAk&;C%wvwQ9Gj&omS_al5Q3CnyKEy%>j4KtP9-NJ39SnDR7gouE4?G08xVkW_us( z_7W4%=W9n9+Zl$svyKJz;7t-YVbEu5z;MY>E4Q36UFCxvVbTUgu;A8Mg|kCADll~H z5*bl9>WV0f633KZhf9{B*YalFRmJ8l60gS_63F3g8r~`}*|U~JOqR%FiEO1FO$iJ| zQw^Wz3O_r7Q#h^RLDn?CO1Hj9ETcgEO!f!eb!q|=9k+AgJ`o2UBcRFPB44EIWM9PUX76wz9K0 zT~uMaEb&1+OqZ?c^^<;tDDkX-AZ7a$qkv|iBJAX&1(yTGl3opyd&tr&D`kE1Zh^h8 zs`Nnz@cRf`=?FfKPipu?lR6!#CGn`rg?PInJup5L9Vd$rFsuadd zvU7VR98F1WjcK3LN8|3wv>9(B*0sua)LE*z#&JNA>gy8UPz`N+ox|FEi&#X^t+s~u z2%PStVL*jY>Lv-&B#d%&4&Rpe4!+AC(&n_v%*_mJgYc?tTx>Z#QEPKo9(5d74awCd!(DUAtn|;~ry733 zA*W3<(_VKj7@54EIXtMJ(@U(n%+R0V=PY2A_LjiQ(N+}R48ViotUj4{oC{tx8zEm< zY9c!w7tdU-8qwoh{}_nue>WVj{Co?M7j(-iu(@Q%2JvHou)DTM+bj`D{8CLE&q;g~ zkBn*fbrO#V+#Gd4*hi*|N&HToZAg3ypXS-Cs%J$EZswml`TG#~j}l+TS9tgj1P%fI zBJni7$-V1I#ZZ~EZKJke>2g{IanA0n8)}x| zYKUvi{~zYtS25s!Urf);K95BD3P!JEyn*fM4eSIO*b{E0XEq4NjXPRrrqi?BoDEJj zkogVqVz`I@yM0L`{8vLLM^#MV&De_t?8CkMzCVzO*Wo_C0gGxBp6xpTYfDM^ySLM>13v0RaH@qm$eV-25S0Buh;_(+2jZ#u=Li|7s}2DN zeGuud;~|Jp6KQz$D&3}Bx!iKV0$0ZyIB^Xp1(u%0;n{0ABXAvO^WmA92Hwrz`}r$1 zu&N$cVDV9Hz~$*n0#Cp4vN9>|J8mCkfbL3gw4bDF@5dp|ZnHSS_tVHk%v=sNoaDI= z;ltGNBfL3|*empYT;sdOR*XZ*n4)-SLXl79$#JST_adZvT*Jo%+8S*0Z5-w8ZAda0 zDqMkM$6Jmar^LrXiE)S|WiT~D897Q&ZW^7LZQwHvd_LVljQ~GI0&XWcc0}+;Tlk~+ zBEEzeVVOiB>>@!22rFmOvm2x>nfSF=Q(-4YuqT2jTZq!vI8H>SV2F4;R5YO!{nm}N zyoJ=-MGEeYU?y6a34D)!k5Q}dQ?D3)fFJtLAK@83)7<|Bb^aB7`&)l?1<&J}zuLf` Z@PfbkGyaOd;qN@JO3Xj-Py8FZ{tJcd)f@l- delta 1067 zcmYL{%X1V}6vltI=h2zYoiLLsNd<5cAa4i*5qSuSiAj_RAtGP|BOL7 z6!C$$v2MBXAJByhDRIiUuvodUSh;co%GQnLhNXD!WF*zq_w+gUJKs6yJN?(Dzne0@ z{`=FP_I>L)C zql(5=Kp_fBel%Coyu<LjB5_jr*Nl&Xu_WjZ0u#tVO}v= zcOZ3?S6z-NI&D&J*pGs#xzbh5q|J$kl91vk$2BK7X})w@+6tV~oaT%oC5%I}bMs-O zh;?<3cw{-J@i}jPcMnUuZ)yTANa<<6JP|Cez)mXEjJyRiSXXSFH!Yi-D#@o4HrlZXS8xCg0{=mv_uJ^_{V6yk~x^|8wZ7qN!`#ig95vA1nl6lpnR{ zzV68k@7sNRs3|hL#^rj3S%ofyVNe<_`eoUM%ctgCx<`FxZl(L15`uQAlQSh7o+c&_ zc{9ioYbVC$venizo82gT5M>CAEcOjn8~1W~EOHf^}6E zy>eY6QT88|h#mAt8QRV>7T@1>JG8Jt1nOfW{bC2jFGv%svW?YRb2z}1 zsILUy#tauF_ma#n8at1z^e)QoX#{#Rj@@l-j!Cgr&#bh%?H9B)%Y=&6ZW^i!N=tSF z8Ci*~ZsnDvC+cRUW?85%Ni>Gah&B;BAC<=B^0f}to=f_q~BeN2xWb3^T6zx z+h<2+_rxTq*=BA}uGb7yP$h^?n?OzbS}A!1TyXOtF8fs}dJL%W!2`dYRCE0X1iyfu zzlX0dL|9A=dr|Qb=s?q;(y(ZpTcBnF}e1dYX_f<_aIbPC$o*%>sY2BH>rf={qaA@~&j zk;1~p&PII?-#}1LHrs{^Gjs1b=ezT*ueEyreR&1Y#&)cZWMeNbl!KGbMd!SC*+1?^ zyJ!2|(_a57jzg=tI9C1m(h4C;E{X!{V;JUBJPP%6BST@{tjP1>Aj93Z`C+GEL&HPP ztl3MgHY5x1>d%;19$@-`jYOWON`ySJD6qh_i4jxq*)d}7?8?C^1PjOx0Rzn5^F7LE zl6jD1b0bfh6_`hj6OZ0oe#haxGP#oyjCM8-i-eR=MHvgcBUBR19IT-=#YoN@*d(Y5 bm(CfgThx8XKLoH{2#Z1;^b0hpNVNU|H3U8p diff --git a/target/classes/edu/ucsd/spendingtracker/view/SpendingView.class b/target/classes/edu/ucsd/spendingtracker/view/SpendingView.class index 321c15ce131c2aa4501dc53b0b5fde19a97b0d40..d3302cb6a127f6ff64f35cdac91df67656cdab60 100644 GIT binary patch literal 8013 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 LZh2DPhuHrD8?uss delta 1925 zcmZWq`EwLi5dPj?GdoN|*ladCxq$?eO*Vl5as+hANlXaHF2My67czlB?p+`eG+ajU zzzRY`>RJn%|L z=O>xhsv(2N*>pJ>St_!T!~bF>ERUyJ@{@9rD!wgHF$4GTYKwny5rbz-WP7BwuPnMz z@6^j;dS9$8L`Ft2LrSn)?`&!7+>{sUjcnYi_bMoaUz9FoNaI)JRC`ggjG6qZ#g{#& zLhP2Sm@RhYs2&T(`rCC0a~U#+PGlC#n8%~KhEWXK&l zk;ZS>)S3n~iLRFu+``8H<*X=bR?vV4RjfpiA&FYAZHtAvR=2gpHVcl|2$ZXMu04>~ zfO3V3JftEl(m5zL)YUCqYgIgq<$S=No{@`3MY#xrR9H=q$j?w9qlKTf7qD`E%YKkQ z8=3_EJC?Nfkm7KdRu7(bPtf71Ta5Y8+p(8Mxn-$9CjmR6t2eNVWb(z zERG|WTvJCe-9UaEg<%&3mMklAl^K}ji(^jMb?+$Vk6=NufeQO2+#j}<1j9Dp1uO`T zVPJ^`t0_$6t)sjnsE?x|OuO}?Sk~mX8Ccy3y(eKZ9dQrYeDamTMdv@2?maiwz%zi&NJk7_^g|4{3z|5nqWE zLOhMApH9r?qYMR@M|Xb}vA7JyScMX_z)!4|B8q`B9KuW-Bl=F$9e$H$^C#w-q_>g= ziMk2W#p*mR5V2x4LWEe%)hMm3=ISD?gi>!~4CAC}6+a=4k04Q5j!U>q>Tba Date: Fri, 30 Jan 2026 13:10:05 -0800 Subject: [PATCH 2/4] fixed cstr bug --- spending.db | Bin 12288 -> 12288 bytes .../ucsd/spendingtracker/model/Expense.java | 6 ++++++ .../spendingtracker/view/SpendingView.java | 2 +- .../ucsd/spendingtracker/model/Expense.class | Bin 1002 -> 1190 bytes .../spendingtracker/view/SpendingView.class | Bin 8013 -> 8011 bytes 5 files changed, 7 insertions(+), 1 deletion(-) diff --git a/spending.db b/spending.db index ed00d5db432162d8e97747a83b8cbb7c3cd8a7c3..50fcb3162f062c40f15121eadaf381bb55b2e4ea 100644 GIT binary patch delta 107 zcmZojXh@hK&B#Ad#+i|SW5P;))*bvnxLHtO6~Bi#J1c{7?apD&Qb7y* onSave){ saveBtn.setOnAction(e -> { try { double amount = Double.parseDouble(amountField.getText()); - onSave.accept(new Expense( 1, nameField.getText(), categoryBox.getValue(), amount)); //! have added an arbitrary number for it to work. + onSave.accept(new Expense(nameField.getText(), categoryBox.getValue(), amount)); modal.close(); } catch (NumberFormatException ex) { amountField.setStyle("-fx-border-color: red;"); diff --git a/target/classes/edu/ucsd/spendingtracker/model/Expense.class b/target/classes/edu/ucsd/spendingtracker/model/Expense.class index 9f3d1aff4bc7aaf19e5b3906f59c078388fa9b9f..2b9c5f1fcfce61b7a121a739a28d23ba79f11fd3 100644 GIT binary patch delta 223 zcmW-aIS#@=3`O5efRIS+TM_m(3`iUSxCkfU4xAyHk{*dNMTA5_0Ubx7rbalCCHp@w z-yiql`S0KT0qilcA1S>Jqu0)!)l(JhK}V+&0~8h6IO33(+B7$+W|hz|>x7nBCUj!y zYXZsbY^O?&8Xk4ZG$fjIWoD!+_w?vXO;w(PxTngcC=RLe@a2daOD&a$3%q diQPC;6=XDJW{*OHjOHxtRcMlu8;Xx+`3EqJAS(a> delta 93 zcmZ3+`HG$E)W2Q(7#J8F88kO?O=O&Wm+=rI>*NJY6Pe{16eh1@R$&yJEWjeltjM4= m`8ALy3g#&@s7%&iQDKw>^HdqsCZ_^EZDaJ>!RTknroEdnC~|VWoKBbq zgEnI#12aPXfPBr=rWWrm@t$vQ~_lafa-vzFuF3jF|Yzv h$unGHxD3>z%fQZ<%$UN!#^?@|XJ=r_p3Erk0|0Ch7cT$+ delta 136 zcmX?Ych+u$q%gCChUaE!VQ+4UxeOdY$iQHxwT;nh2cw@QoAz$Tph%Xs7it1 e62oPn9z6zj#$?761~x`_pgcPRQ_kf7ay|g~!xumR From 1ea9871d0939eaccbf136c22758c74f036abc750 Mon Sep 17 00:00:00 2001 From: areddot Date: Fri, 6 Feb 2026 13:35:51 -0800 Subject: [PATCH 3/4] lab5 changes --- spending.db | Bin 12288 -> 12288 bytes .../java/edu/ucsd/spendingtracker/App.java | 10 +++- .../presenter/SummaryPresenter.java | 41 +++++++++++++++- .../spendingtracker/view/SummaryView.java | 45 ++++++++++++++++-- .../view/charts/BarChartProvider.java | 41 ++++++++++++++++ .../view/charts/IChartProvider.java | 11 +++++ .../view/charts/PieChartProvider.java | 43 +++++++++++++++++ src/main/java/module-info.java | 2 + .../edu/ucsd/spendingtracker/App.class | Bin 2295 -> 2662 bytes .../presenter/SummaryPresenter.class | Bin 2351 -> 5119 bytes .../spendingtracker/view/SummaryView$1.class | Bin 0 -> 1464 bytes .../spendingtracker/view/SummaryView.class | Bin 2151 -> 3732 bytes .../view/charts/BarChartProvider.class | Bin 0 -> 4038 bytes .../view/charts/IChartProvider.class | Bin 0 -> 375 bytes .../view/charts/PieChartProvider.class | Bin 0 -> 1024 bytes target/classes/module-info.class | Bin 277 -> 327 bytes 16 files changed, 187 insertions(+), 6 deletions(-) create mode 100644 src/main/java/edu/ucsd/spendingtracker/view/charts/BarChartProvider.java create mode 100644 src/main/java/edu/ucsd/spendingtracker/view/charts/IChartProvider.java create mode 100644 src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java create mode 100644 target/classes/edu/ucsd/spendingtracker/view/SummaryView$1.class create mode 100644 target/classes/edu/ucsd/spendingtracker/view/charts/BarChartProvider.class create mode 100644 target/classes/edu/ucsd/spendingtracker/view/charts/IChartProvider.class create mode 100644 target/classes/edu/ucsd/spendingtracker/view/charts/PieChartProvider.class diff --git a/spending.db b/spending.db index 50fcb3162f062c40f15121eadaf381bb55b2e4ea..9ce3e0cace8e0277ecf9554e0164e2b36ac9b90d 100644 GIT binary patch delta 96 zcmV-m0H6PWV1Qtd8vzxO976#Wv0$VR3IY$<01xgD*blg~5g@7$leixgG#d#802?O) zVrph&W)uqr02LnsGc+|cR8m1sQ&3M*Q~_BK3IzZc6#{d1VP|JXPftVvva%rm4*?7G C+Zi7K delta 96 zcmZojXh@hK&B#Ad#+i|SW5N=CE(QSx2L2r&xLHtP760TN@**aluEC693=9nV;_6Hp vX~o%Du6`k|K_QNwe!f5!V+2r2L|T+7qqsCXC8^lW-`|Dt*(Qbm{EX}X=|&nO diff --git a/src/main/java/edu/ucsd/spendingtracker/App.java b/src/main/java/edu/ucsd/spendingtracker/App.java index 8f4a7f3..07a1dba 100644 --- a/src/main/java/edu/ucsd/spendingtracker/App.java +++ b/src/main/java/edu/ucsd/spendingtracker/App.java @@ -1,5 +1,10 @@ package edu.ucsd.spendingtracker; +import edu.ucsd.spendingtracker.view.charts.*; + +import java.util.ArrayList; +import java.util.List; + import edu.ucsd.spendingtracker.datasource.IDataSource; import edu.ucsd.spendingtracker.datasource.InMemoryDataSource; import edu.ucsd.spendingtracker.datasource.SqlDataSource; @@ -24,8 +29,11 @@ public void start(Stage primaryStage) { SpendingView spendingView = new SpendingView(); SummaryView summaryView = new SummaryView(); + List chartProviders = new ArrayList<>(); + chartProviders.add(new BarChartProvider()); + 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..9beeb6d 100644 --- a/src/main/java/edu/ucsd/spendingtracker/presenter/SummaryPresenter.java +++ b/src/main/java/edu/ucsd/spendingtracker/presenter/SummaryPresenter.java @@ -1,18 +1,34 @@ package edu.ucsd.spendingtracker.presenter; -import edu.ucsd.spendingtracker.model.Model; + +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import edu.ucsd.spendingtracker.model.*; import edu.ucsd.spendingtracker.view.SummaryView; +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 +37,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..b9b0e9f 100644 --- a/src/main/java/edu/ucsd/spendingtracker/view/SummaryView.java +++ b/src/main/java/edu/ucsd/spendingtracker/view/SummaryView.java @@ -1,5 +1,9 @@ package edu.ucsd.spendingtracker.view; +import javafx.scene.Node; + +import edu.ucsd.spendingtracker.view.charts.IChartProvider; +import javafx.util.StringConverter; import javafx.geometry.*; import javafx.scene.control.*; import javafx.scene.layout.*; @@ -7,24 +11,59 @@ 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 Visualisation Type"); + chartSelector.setPrefWidth(200); + + chartSelector.setConverter(new StringConverter(){ + @Override + public String toString(IChartProvider provider){ + if (provider == null) return "" ; + else return 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 setChartDisplay(Node chartNode){ + chartContainer.getChildren().clear(); + if(chartNode != null){ + chartContainer.getChildren().add(chartNode); + } } public void setTotal(double total) { totalLabel.setText("$" + String.format("%.2f", total)); } - /// Hello + public Button getBackButton() { return backButton; } + + 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..63c6f6b --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/view/charts/BarChartProvider.java @@ -0,0 +1,41 @@ + +package edu.ucsd.spendingtracker.view.charts; +import java.util.Map; + +import edu.ucsd.spendingtracker.model.*; +import javafx.scene.Node; +import javafx.scene.chart.*; + +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 (Node)chart; + } + + @Override + public String getDisplayName(){ + return "Bar Chart"; + } +} \ No newline at end of file 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..bcb2349 --- /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); // dictionary + + 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..d7e93ad --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java @@ -0,0 +1,43 @@ + +package edu.ucsd.spendingtracker.view.charts; +import java.util.Map; + +import edu.ucsd.spendingtracker.model.*; +import javafx.collections.ObservableList; +import javafx.scene.Node; +import javafx.scene.chart.*; + +public class PieChartProvider implements IChartProvider{ + + @Override + public Node createChart(Map data){ + + ObservableList list = {}; //! here is where i stopped + + PieChart pieChart = new PieChart(); + + 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 (Node)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..79db889 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -2,6 +2,8 @@ requires javafx.controls; requires javafx.fxml; requires java.sql; + requires javafx.graphics; + 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 cfbf1cd2c3e49f325d8d39ebbaea1109feab1028..4552d0911c5069a9ea1170cd0e47c54c89d793f9 100644 GIT binary patch delta 793 zcmZ8fT~iWK7=F%z9Cle4u{1X-shbC>HmIG`TXnSCjd!^1EnJMo!Al$ zp}(q^%6if;#BQoot1CDMnPbQdvc7zyRNT??FN9IA>2t!Ew`R-6cB51%8VUv>doY3s z$0&pEpOz(~Vhk4;9HLNQ=nkjs)3T^+>Ps72#e6+6yvA{nVRFAyGuNE~p8_2dDmoBl zSPk#LIc-)Q5mT2ua$-2cafu>+a+5%r@C>(*Od)p><9IFMJ7yrvs%rCCa zkb)RwH?A;ru2hSaLaDMDOdBHq(h3yARTbBee8-($X~1U({}Z=HjAI6--}QB*C$*gy z<%}>&VxwG4?^cUxYr?Q_3_W9hllo5`UFPC{SDBbKf4D-fM=Bm8XLj*A>o#BWetDh} zdg#4&%(r}euZd8cYrKWQTod6#3`@wipyxEF*3rax+}*;YwQy;?iK)2ULX3ckxS}be zT{D_nliy?ZfaDxdXqlMf51`Hf delta 456 zcmYL_%Su~O6o$WZNzOjUqvj&g(}D z1bu{1Xi5bizz68KbkMn@&WbBKC>z#hvG)J{|Jr|={>Ee1|9)HnldL(I1}*x=3M$!E zQzxuZm8Q!l!V|q_ZP{6aVSQtF>ZM3ygGYv*+N{@LBXjZPp?+`mCO;k@@0QOBN2O2W z*@8pgy&|nY+lh1zS21W1TmMix**`itY~LvF?!7COJ#q~DjPUep#jZE?@90mRQjelb zKFhq()9TcS>F=t|jfkBmS$Fg=HFzG_L8Qv#(77a2lqOoGJ5-nCidFhUH*k9r1A!B$ zZwysLWZp@;?`jf76LFeJ@qkVONsuC>g?U=Z)5bRK)QRfg-VmR9>BO36jADp>eUs;m z2{tY%L&mWLF~tNgumw5BOI}Id90R&d@}a^IWTBE$+#&dHI^&di(lzH-0&m3ihr z=Pv;0$GT0=3@0 zteZ$iMiUvAdp1la<}Aa_I;Ox~m%TnXTGpqZWna|zp`+Z!Nooem9E@~%-w6E;(s1WaJ7f~m||4J`tl>j$?4 z@-UjQMaNdOkwSB(tKvOrCe4^@I|AD~I#(-;*_P|r$;hCcnzaY)#b_AYuwBCq0&S~2 zx_qOK9oQ*QMI9rqnIdC%6=lclq|`{?Gm(kejOi>$nkyPtV;64Ha3gK;<(J>AqXV5} zs1c9%CzAp#9VLVsEa-@K-dl}s^lIo~BB}H$q>YZ75fRW5nc-C0T@tA5@OJOfaSQhH znGP@_9U~qvUSdwn9;f+H4Y#gWDat371o1Wc(Z<4)WqP)&~~tbP@Lf$Ke|N$)Gj?VPS>KHMSk z8WyM-O<3l5HZ^NHQ<5+O^`myoNKPA0LO%P80e3z@zTH~B5Ut~-Ku{Gkfg8)8FD-Wh z-Q_o~sdxfSt4&@?=gr!=QVtawh*x1=q9cfq zOc)>ga5fz`TvOI!#e7wV?$L8I!oy`<#mul8A{A6R0a@ z)|6wKbR>*fn6geD4Py=o4f6swUB#tA+B0W6OFE8&?J%?;Q-fN2Iy#S*$Jv7;f0lGi z!PdY8sZ~a)gc`E5D)_vS87Bsk zw;$H=5xG}3xGCE;l9T=nCrjzabbK5SdUaR5BzU9%%j`CMQpcwxnzC#88usBcIv&Dj zsX6ADB&X__OikZ(l>{V4u{?T(c${+racIWpb$kI2vv@H{)!Cs$Ce8lOO5lkoGp1RbR(K%Cq4~ zJL|;EI}_6K#>+o=ZkFXpAXdIE6dUcDZ=Q9+u%>IuDAo?xwkyAz(qpDOZ^tuX`~*MK z@Kb>u#Uh`u7VHydWK`kDjm9zdI@L~oj$bf`Q^h5LXG_bEf6^1~%{7_!QQJO|P5a*| z3S2*6CDd4TaEkrBbo;fx^i-~YwzM|-k_U}sa*{11S`)&L1^o8EdYU3pYVj)>*Wc>+ z7B19i_)RS?_-lXEaY?QHfor7eh-I11VA9C2+iUn62lqAbUI`=(|KKpU{#KR{4^eEV zF_j!nEBMEmgm?Aw>xZiw)M}V(3>S31_f|Gy6S%}v0q(H7x_i!|rmOc1>bssm!$mab z(3->be5hYWdj)2^yDq_U-&WirS1XsXyMmdsFNghwH+@~_aR|s^ps>`+rMu>mG;5q1Bm^(UG=GT(?Uncep|0*Tn2|(-P$WGTtTePv!95=1{C4NS^rsOb$vsn$o8y|KK|g{k3LgQA?t;I zRI*O8t&VWdT!Jny%XmuAC7G5oJ2vqOY$30=5}vja^3@f{SBLN6X^N80RYKHK2kVco zF delta 951 zcmZ8fTTc^F5dO}#-G%Mhc3Y6ra#g@yxD-V}1-aOwqTsEyq9SyKl~kKTXhq+MKY^To zV0;G>t+6r0Cry0v(ML%1k-wnMwha)o$$aO`nfd0Mnf)8w^6KCJly(73z)&DD3~cWE z#epNR8Jly;Bbi*LFv^e&i5(UYTe4GZvmReK#bA%EESV~7aB?W%43kGO3sQ&f;&4N! zxb=+rilJGgrDj=ymm$2l-zt7Er>eq(dX5ul5bx}RawCTy0kLOK*EXY7K?_5ZDA}7F z9BpV98AnvSb$k<_K|Bg-$kx&=O-r&71|r=(AE8FxL;C_x5p|Ig zd_WORJM=2yBw1HEQY98^89Gjpuf39u4s_Cuc&w=tw{>zONSO>Fgg2_?M#&-3qa5k} zfXETGTK3kFxcV|}LnZ2vRz?q%W%Tu;ugWz}rL98Vs%U~}5od}R`k%KE8y-?@>E)G_ zDlx+_MyhnZgchC6dwH9n(y~<(XgQW@tEB3ZwTWtKiqPuHLlPoi!7ccN2?k4u&6-`N zIy{X=@1oJUk9Fxe?9zj)xJF#p%V|u99aD6aa055XIE@)XtA`}>h^>%o 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 0000000000000000000000000000000000000000..24b093e3b6942a5d3e83e56c47883d1686571db1 GIT binary patch literal 1464 zcmbVMT~8B16g{()Zo4c{5fQ}?&}-{Pg%4u% z!T4t4k22m_Hl{-P&^9}BXLioH_nx_TfByRV4Zs?fOc)G~XvA*pMGZIVh@jyIO(nVa zPDr=wi}!9lZnwES+#$QTXd=Tfb-=rP?}HmFzvb4IBt$g~x7E1qsEAKF5s$oOq!7yZF5LpWY7`9hwjP;bfRC_3Uo#9tcnM)7YYtnYD2p zz}_IW4pDUm~oM z-lMMquN6kre;Y#WhYb_dcIAspr6*7Zdp!t*thRU*2`c^Erij#=FjABuH4l9wSfQYM zimX9;Oyp=kPu4RS^arep^NEJfus_nuz$lGbIs@E8fkr#AEnLGGt(X=&W!R!wGmJPt zkR7{m|lH zGUE@KK~5f0vTGDzG36)|P6wE;INvdOj7O)b=++Z*5NsNADQq@{Wh>4xO6Ouo&q{)J b@Hm<0u|RVME{3s4mM%4|qy9am$AJ4Av-NCv literal 0 HcmV?d00001 diff --git a/target/classes/edu/ucsd/spendingtracker/view/SummaryView.class b/target/classes/edu/ucsd/spendingtracker/view/SummaryView.class index b9367867da5b64701688b10be29a4d563db900a9..00aea1172afadbd9754cb136a1cbdfec6d06f35a 100644 GIT binary patch literal 3732 zcmbVP_g@?59e$3X6Y@F6GBzPLAUhD2K{2+I7*Ut$h88f5h#V!g+mm#lGbf#T_llA3 zz4uDnbnl&{L3q?{I)CVY(*6Cn>k1;m7P>X7XADchiP>F*S-U74+lqU)3DRb$W1=jCT~yFso7TT3@xg3fcSO># zjI6L71)a6&C+$MUrX}QPN}9_>U6dU|LF)e0qqFx9fT!Dy&rC`i794xk%o$GNB9%Pk zT}{$6-7FgW?FxdE6m)e#FB)VCjhaPMTvSls+m}+%FlpzE2#h* zDZ7iKFBKX)$1>nYGGEXz0s<5vbF!po83@ADJJpv`@g@bw_F6W>ND4PJc5z$8D8^+> zJxeAvOkvs=wxH)^O%bU5cKAXV@G#z@pkr`peNdLgvSXKvxxuV$+0IDp(M#UP6Fj5g ztrE7dv{GzXMi{dS4kv@cjg1#|Yr{1OaSJ-axU6763SDA~4!Y)x#z<`V@zQ!CwsW{< zn9F%F63f_Djv87p69$8PdWXR0Iy=10C5&}3xMW%u4I7?*a_a1GB8)`^ZGLseQl?wh zEz{M7X%}OQ8zrXqDWo)9k#--X-7KL(Ni0%MXw2M>-YLAG;T;kHiQa-^EL|~kBCp~a zUATXJRyC-uGZ9?HyCe>}f}!3ARCX07F_3mNuNsb!bsgJ*t}IL|sFR(0 z@`lDXd{07S&KurJ=J<*R3k3xS0+*6RKtW^g6tgM}Tfvlvxb3i^?4UjEeSC;A{?(cc z#o(D;XO5mT%kD_*JW=bBsL{-Gp1A!9^yGQ@!5Z@B$(&va9Fx6ZQ4ZcP zzRs4_Jv6+e;wAQd8DhV&`|>0B7G75I?Oj(>c9}8K@Ev?tfx4<&W#jUaG;hks-520f zF;~8iAFBAlE(!kB(C{Ptm~buGPC;kaz2L`Z*I=myU=^mp_=&Q9eyZVT__>1Cg1%y~ z(6YL?Vv0OhuF#8uI6hWGeznDcFxk?6so__$`KU5bY&#NG87~FO6vN4MmlJaPEz)^6 z;eBMY!OLamHPY-A$gT&;$$K$v4@ow*=N?4!|35?`NxST1jZ3D?)#j?UHY9U^M-#R! zTt4ecbB4&|&Gyq6YZ`G9?f(sasZ3_OL@CRKmEUpsq_{^PVa4H8yGKE+0E8 z-e42k=VUFjRs4lR`2M8KaNkGv$$7&SbB63YE>5z6)-!P%P$yqzT-C|v6ThSKQN-H= z-kHWdpFCVQ@{CVD{yhvR*GXN+(|`AGA=-Z%E$J;B+e9muZRzOoEwpbU#?2|7cWt7Z z%N{QKHqqbz8ctU*+~0yHDtL+)qv;l0+`?D|6aCRk6+A7)Mc=lCx!Hl}d<6^rucI~k zc7M?wO;+$MPr6(1Tm{d|)ool&(~fsmkl~hsms*go;JVyIixrf(h(+IBf!kk!Xb#=M zdb)lfnQq{DYck#F>3fm-lIakSx|3;DvL@4E$(X!}_txRct6n@l%)igDM!_gFKo0JM zIKlYza5cP-Ft;h))3Nw-+QWF$0onSRB)TWe}MddGfLrC U`7J+x!k_V1!uU6?8%S~Wzb7v3u>b%7 delta 977 zcmY+C&vO%H7{@>FCf(g^wjoU$OleaRX|dT#LqPo{JV@#=UHM^ePWqX&=v0bV_L(ThjNXV=WA^Ul7{^X&7y&-eTM_$2>pI{njM z4}Sp8^1g+kDCv9g(#NNF^oJ^!=yyrrSnSiEtAm3n`V%NJE`695Ly8gog~}eDyA=fO zmd$=edamBMQ3%?F%AGC0)$uzHgXF?2!`d-MPmH)&*a`9+v=~ziZq{$t*Y1?p{q{{i z*xo5$Y=iZE8>&q zN>^--=ucx4N6Ico8CKX~M6lEJZH_5Y%k7}vEL4Tvs=RSXk+V6We~TS8Q0-Pb zq0PFS;TfGbPZge14D^_G8h*RT%WJner{k!9-TY4nv?NXFh$7Cf8IWp-;lc|Y}iANSf?xa{hiq{ai z>Fwcq-;=8Ck-pD>sDrgkc8|yIbHMwC(JqgBLmcih>1CemG989yX7)I~IF)&-%hTSs z3}jA*N|)2S<|Cf1#ipvYc=*3s>l1OH`W??3T)h{OsmMJYQAiROV*7;DC@zQSm#s+2 z+|$f5AoIzvzz`c`c~Rc%|A#Iw@v>O661O1bDLLnv>J@c)S2i@PJ|D4qCH{z4Yq2LD zaH0Bu%MW=2y1e}_4=2i*6a3--VB~ukl7{OvB8*l19!5E`A*$?a!7>O-3aP-E(I}4_ f8GXGxG1j86b>0F@l^wvT69@XZmagrM*SqTO z%2;hFg+AzmK7h2Pw9qHeLfdI)I!+VMboizHq0_&q^t-z&dF3b>&oKSLTJ6=j-#zC$ z=X~e--~YY#4*-++vw;qQ2UVq(ua*5u-mfaBVmZr!C(EnK%dcDNnS6OgdV!xmCA}&A z?Qzdtw<^jrkQV5>B-dr$md=~?_7VQk*OL4iYUj<~Q8ay>GqJWJ8-Vf6H~JnuF! zf_qpOvRqcxK;U%SV_SE}bmhZzE!CWIV7X5Ilr`l#er-*8#U32Sn1NA&J=&GXka;z6 z1V;soCD(gImRAJsN@lSg(%8J_WZcAk$aCYe3Qo&F3fwc=ERnKn+iVKD;Ilt`<*n;N zEm?j*KOVqw10UI@=Lb* zp#x`4JdP&>I++elUVow|V?Z6#oQZSzOq6yl0Xi?uv?r9I9|Gr1T)=|B;F?@jEX1-5 z&RfBXF3CVT0mbUxwr+=62^nu5{1iTG;Aw$dTiQrFVB&N5Jk##0U@oX@b!;h=1{d=> z>(ay`%5;83`m%gha7N@|(YVBYerP;Aqq7eiUDghk%FLlsHbh86&p zbE`gHuS-tb_JJOu7;XV|F7NMSUrassb@17{o7 zx_)V!T9mAV+gfpB*&k?~K=o>43Y9|hrn-E%5g;(tdU`}^Bm9%mS;&20rh1)fpA6 zxD}4uAK?`PFLU5+>y72CyQ?Z+3K^xLT#{vulDdgkahW%ywe2N=|0KhWcShikNvC2f zf28EPtF>y9gE)x^YFjp*Vsa~r4PsYEUs6`ELT z!_zOi@mt=?$Coz7sgUDKmTeaVRmPll9OX^f()X2b;BDTBu8X)`eHi$?z@0ZYrO-#k zWZ*r4A#L2g%h{G%glHe>8V)g|DgJfxW|`)b|5ETX!?!%2g3rz)SCIWHzjVOlXIHqG z!5)4$BLm!mUcRx5a4W6!CA9;$X%O)mL9=|nyoJ3BS1>TMg+V@Zvs)NiI5vI-cNEfF z80ONULg&$3=QZ2~T*bW|$fY-NEZ2Dz_jllYu5%L~yNVM61>+r@$Qf5bM&HL|p)1$5 ziK+K-=I?myZ-Q%MnOx>y=*?wv-PbS=Y~rHc^96y|Klo=Zo!Uetm;MX=N{2BO z7y%ejH=lisWk2H>VFV9g5EIB@fmZ;Ft5w{A8V=xju6>Wxy-aU44^M}LU5d4zaXe38^IU=$vFa%P?I<5#!6WJcy1DFoSLb!oXnzdkqX47&3SrHh9y)aiV+$&+=2JdYn(4 z>Qw(%H7UtNA5J7X6$RLr)dCQ2J_QO@tyGOL422-b`b2P(1q{g2YmK(<;Pt634Vs3;|Hq3%$5E5#IRH+oCoM7qyK6}@g zoP7fO3eMKl5Lzk=d|Itp2L(skGX?Iv3N9y$&Ju&M_()ZH)#;ZHtTmU6OP6!1V3e7n zq!2wTpnog3i=FK@vTboHafS2Sw2$iA%v@YqPVaW)ofaHsrmie)m$Z@4i%DOszaJ!J+68jO8y-y2dRH9+o30VuX3Y|~*BYihMpk<4B@a67)IR*kLRTokMpz{VRmO6rxQz^!#n(c* z|1QPHXpi+V-AtQBCrg#mInWXI)am^-UkRGX$0_&EjM1hHR|))lt&9k@7mF!%wI4{2 zTd5Tdj7B&=+@(%se-Q}k%h2c6o$peYE2S-Zt5_II4~_O|Hq5v0sMUB5g^3e}hcdL? z6=ORCZh6nCr1DsSOaxt}|DQieI!@!|Kph7fa6Os+4Fb(2sVO;QYfz<~L?&A^VFxk{ zJiZulAK7oTvI%9XTzZz_4$cTmr>W=&IAa|dS3H-Aj+(2UR@&Z4sD*7nE#kL Date: Fri, 6 Feb 2026 14:48:49 -0800 Subject: [PATCH 4/4] colour fix --- spending.db | Bin 12288 -> 12288 bytes .../java/edu/ucsd/spendingtracker/App.java | 1 + .../view/charts/PieChartProvider.java | 28 ++++++++---------- .../spendingtracker/view/charts/testing.java | 15 ++++++++++ .../edu/ucsd/spendingtracker/App.class | Bin 2662 -> 2745 bytes .../view/charts/PieChartProvider.class | Bin 1024 -> 3616 bytes .../spendingtracker/view/charts/testing.class | Bin 0 -> 936 bytes 7 files changed, 28 insertions(+), 16 deletions(-) create mode 100644 src/main/java/edu/ucsd/spendingtracker/view/charts/testing.java create mode 100644 target/classes/edu/ucsd/spendingtracker/view/charts/testing.class diff --git a/spending.db b/spending.db index 9ce3e0cace8e0277ecf9554e0164e2b36ac9b90d..a720f82858e79f4a5052ada82789069eda69f75f 100644 GIT binary patch delta 107 zcmZojXh@hK%_ucd#+gxSW5N=CK34u&4E*o-Z}9KuU(G*jv!Fl+za2k6D}$&wV_H^r zmVbzcYmkKyA1i~fJY#xBT4;!;k7tOdYp|a<4^WXhV`XW2nyX)kYfy-zr=Ks7WwH5& Jyt)7*KL8-496bO4 delta 73 zcmZojXh@hK%_uri#+gxcW5N=CE++mP4E*o-Z}9KfEU2)GUqPIml|fpbsWc!Bme*a diff --git a/src/main/java/edu/ucsd/spendingtracker/App.java b/src/main/java/edu/ucsd/spendingtracker/App.java index 07a1dba..80241a4 100644 --- a/src/main/java/edu/ucsd/spendingtracker/App.java +++ b/src/main/java/edu/ucsd/spendingtracker/App.java @@ -31,6 +31,7 @@ public void start(Stage primaryStage) { List chartProviders = new ArrayList<>(); chartProviders.add(new BarChartProvider()); + chartProviders.add(new PieChartProvider()); SpendingPresenter listPresenter = new SpendingPresenter(sharedModel, spendingView); SummaryPresenter summaryPresenter = new SummaryPresenter(sharedModel, summaryView, chartProviders); diff --git a/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java b/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java index d7e93ad..fd08c39 100644 --- a/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java +++ b/src/main/java/edu/ucsd/spendingtracker/view/charts/PieChartProvider.java @@ -3,6 +3,7 @@ import java.util.Map; import edu.ucsd.spendingtracker.model.*; +import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.scene.Node; import javafx.scene.chart.*; @@ -11,29 +12,24 @@ public class PieChartProvider implements IChartProvider{ @Override public Node createChart(Map data){ - - ObservableList list = {}; //! here is where i stopped - - PieChart pieChart = new PieChart(); - - XYChart.Series series = new XYChart.Series<>(); - + + ObservableList list = FXCollections.observableArrayList(); data.forEach((cat, sum) -> { - series.getData().add(new XYChart.Data<>(cat.name(), sum)); + list.add(new PieChart.Data(cat.name(), sum)); }); - chart.getData().add(series); + PieChart pieChart = new PieChart(list); - 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 + ";"); + for(PieChart.Data entry : list){ + String color = Category.valueOf(entry.getName()).color; + Node slice = entry.getNode(); + if(slice != null){ + slice.setStyle("-fx-pie-color:" + color + ";"); } } - chart.setLegendVisible(false); - return (Node)chart; + pieChart.setLegendVisible(false); + return (Node)pieChart; } @Override diff --git a/src/main/java/edu/ucsd/spendingtracker/view/charts/testing.java b/src/main/java/edu/ucsd/spendingtracker/view/charts/testing.java new file mode 100644 index 0000000..6983227 --- /dev/null +++ b/src/main/java/edu/ucsd/spendingtracker/view/charts/testing.java @@ -0,0 +1,15 @@ +package edu.ucsd.spendingtracker.view.charts; + +import javafx.scene.chart.*; + +public class testing { + + public static void getNametest(){ + PieChart.Data n = new PieChart.Data("thing", 4); + System.out.println(n.getName()); + } + + public static void main(String[] args){ + getNametest(); + } +} diff --git a/target/classes/edu/ucsd/spendingtracker/App.class b/target/classes/edu/ucsd/spendingtracker/App.class index 4552d0911c5069a9ea1170cd0e47c54c89d793f9..10353e47566e046e86dd259305392034bc70b216 100644 GIT binary patch delta 526 zcmXYt+fGwK6o$WjX!pSl6g-3h2GGxnJbsF8-?ndTy^_hxmc?DjN&<5)-h|`O>#9LLQ2nDEA}-*vPbrio{6-z z`izlozFjvc4uAgIrMImSow9rFiQ}?C{lV@S%;34)GKeiyN?XP9)_UJ!wXn9?#ALV~ zkmb(zn!RU5Uk1G5xz4&@yd_aRA)Y_!U+&bdavF^0>s&e@ZnE4UnOC-o)VY#&8;mtC zQRUPbPkRkAQg|cnEB|80P30TtaA*}LxMhe>t~7q79~^Q zJQXhRo?$-j5)aK(jx7;{B4SR;?_!A94)>VG6v?;T=Yhbw*<^-?*dn&dEORnYf;^AN z5fxO9c^>10pans?f;+<#mhc4H!ZJ_Aa9+#?v>X2$R;0n>nfy_|e=_-^IhGlY<;xBu VLQ8}m1962AUyD9+UJWbP{sBW|S114g delta 488 zcmXAk+fEZv7=^#-%(OGZph&qxGbv>CfrU-$0I1f|y08NjuTe)xR+_ zV~=@*428H1n?rlvxo)XRyWQrad-hDg2xHZ^af`Ly!!PaTtKDz*oJ&r&E=!qTPID@Q z?{U+jsj#!Ywf27NU2=A}w7R*z8<634$Q^RW|C~>Dd?93!qWR!`_VaRWP^5j6^rsFg z3>G6Na?7N%UWJkBAs!{ljAs1`nPQn6*&qt~nkOPJ^1pHGNTW7^_8~&;ZFoeSqeJTg z-CSgVB%^dOMT!~Sl(@_WSJp`^)XL~3zOq1&qxT=!*gE9qr`cg3iyIHGRsSaeI-gLLS6q_dY?IpSb4QD ltS3v=z4o2?>IY-B4+g5xCw6}=a@9d1mRMG`Sg9%B{0H)eN38$= diff --git a/target/classes/edu/ucsd/spendingtracker/view/charts/PieChartProvider.class b/target/classes/edu/ucsd/spendingtracker/view/charts/PieChartProvider.class index 70bbb1a90687d847532eebed0844bfb66e1f96e2..1965f81973c45a4165a4dc9ff3607468c14f8d54 100644 GIT binary patch literal 3616 zcmb_e`BNNK5dI#!Fl3nsfdE<%ztm|16L5xnpF zK4ZN7#b33`B3G5=PnKo*H>uwo3$wVPsM0E!nfJE4Uw_?ScfUXWy7UWxgZN%SjX=L% zC~2j;~>Nnsatunv>Eo{B^XM^kxlL;I`a`oLGx0BhZj{bm@g)1v)x&0mhPNnA)f;X1ap) z^rGhGbxYUA=p~glO&Bwl^hyrhl5123uk6Y^wM}i9$IaNzQYJhq2xrzV5mRQU>Uk-& zqFq6ozz*LzI+M3eli@dP%he8_99~_i*oL$~i#_G)&VnDOgN`GYa)#>(?CxAa6E`rv zBI}D~n#q;zDz3q`Op?s!^&(ZXA;>jHuh9&xYeDR$OIF~YcE}i}m!)~#$u!`4>{PHr zU~@%~RqVnI0?M@Q+%5C70=wcNt!AlfQo(M4?NK zjUcgj1X@=)9IMD?2;8IMUgQMY=jEJE&gG?d!tiE&_Ic9s*d!tvgbi%P?I0_0Bq@yH zn1XSEEfxIoYhT5ExSwfvb#KC3^1D)NwOEi!eK@Y-0kE|xv(g<463kY2+UMm-6{m2T z{gh^M`V719q~RJtlS_7<4%%UXN%foHDrfv|M5>rUDc?|TOY0Oe-7H33T;STWLNyA} zZmn*4&Js&+J-L8tzOZW=d17y=6por>TVvc zBMeY{B6Lmq^=hjq`lX$;=uQd_IC)9v*gOsgh>8*xIMWKjIGOb8H5jm2zdtPc-H<76 ztHRi9SJ3^QQt>pNp^7XN)=)bf_?a%!Ho?*o*m%KHg9D(l$fJQLkeaYdPF_E31jV#= zK=1eYPoRfv+jDtODURyitX*(ZconZJc#VWztzW}hu;+9w7bJ&*a$4runwM0(fj1eI z`PD6fKjTq|G(+P@rByI>wz1& zniHHrnZ`Q2!hRly6y+=CYdM3HO?W%ShWVZf6Z2GkS74~~KXJ4PAEfXxK2`7u?@<5B zNEo-UCm$~7cPw^)uwy4PmEeCZuVqQTc{%2D6IUAF zg74by^GN-~j~b|a)&-jl*vxM=6u?zzNvC5!;e81)q<1kU~adv9VHCwhP6Ny)&={b=BK6IWaKY(*OF9GTm2fL~cUF@o)! zp6z&)cg6yC1Za*DJUxxj_+Jm=A)-oR3J>EEVoGC_8jlfEA9h1>KS_(*{JRF@lI2-> zT2r9YP8;Pz8`CQ`X1F)Y-K$aaH|KPn0-@k~1>Fi)3XSqlz`y{XehPZ|_EV5(KI21+ zCt!Ch0g2G%rj%cBk?J@dN>Hc0`!f1Z?OTS`vy8{jY5S`7Txx2(9gv75zU5iK}Xc{eyB8W*BRPX~tEH>wQxo}_XEeAm%{sp<# z!k?g(prF0_do0CCAR)EIzIikI-puSi7Vp%|=kMz~0PMkX9AX4E?^!8Ikj!)Amh|F~ zCy?&2kX3Ewn$?C7o={Cy%wHB4_h5>$csxVJ>&rwAwzr93gpg_#e4g0CgggZNw%wNMn4&L zX>mH7|DT)wJVrw%to}S*haAi$ArA8d^5y36!BIigwkl@?QYM#mEAVaBJzx$ekSkY4 zDzkblh2@&tDl8JvaBn);J9QOkVKqB13((45R(J0Lke?1UVtK^hI|cUU#Dajo-mACD`Qq=WL+Al=pU>4dLIA) diff --git a/target/classes/edu/ucsd/spendingtracker/view/charts/testing.class b/target/classes/edu/ucsd/spendingtracker/view/charts/testing.class new file mode 100644 index 0000000000000000000000000000000000000000..fd385b1fd6d97099b0618e13f87ddccc46b8fa6e GIT binary patch literal 936 zcmb7CT~8B16g@+?-F8`MZJ~hp0f^eI*zxs#kLCN&N%4F=$+^dB}2JA^2M+#B4y(Ar=|B)%+P56kESNW>_F-r5lExbMu}m~ zNc{MP$G!~ZqzAsMWXm+Oxh=HFqs)*cx^R$tUZQc(=b(tH5xm4ut+l6Jc63B}&26t+ zzzSAvTs}2~&evGWz{M3@r2&k_G>^qewHonVD%AuaMbI<^*Ile(oxx5eGc44+vs?~t z;HHgDhDxI2G?I&3xJ?)b27DM2-#K!P5sdCO67-9PK@+qBp(wXn`*2o^*LA>f*TuZC z(h|{tJgS_N$l!EFIa;#kHu9x<$5;1UrTpRi8UnZ%w9 zo#-*qYE#TbKf<*mY)tXy6Y@ME6tF}LC%AKTs=-Te>$sERKA_m(T0gKg#c)U)2q8lXPU