diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java index 3c02553..4ecf25b 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/Main.java @@ -119,7 +119,10 @@ public void start(final Stage stage) throws Exception { stocksInFile); TransactionsView transactionsView = new TransactionsView(); - new TransactionsController(transactionsView, eventManager); + new TransactionsController( + transactionsView, + eventManager, + player.getTransactionArchive()); // In-game (Change "topBarView" to "topBarView2" if no summary section). // Dashboard er default center-view. diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/transactions/TransactionsController.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/transactions/TransactionsController.java index 63bc088..89c30fc 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/transactions/TransactionsController.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/transactions/TransactionsController.java @@ -1,20 +1,67 @@ package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.transactions; +import edu.ntnu.idi.idatt2003.g40.mappe.engine.TransactionArchive; +import edu.ntnu.idi.idatt2003.g40.mappe.model.Sale; import edu.ntnu.idi.idatt2003.g40.mappe.service.event.EventManager; import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewController; +import javafx.scene.control.TextFormatter; public class TransactionsController extends ViewController { - /** - * {@inheritDoc} - */ - public TransactionsController(final TransactionsView viewElement, final EventManager eventManager) - throws IllegalArgumentException { + private final TransactionArchive transactionArchive; + public TransactionsController(final TransactionsView viewElement, + final EventManager eventManager, + final TransactionArchive transactionArchive) { + this.transactionArchive = transactionArchive; super(viewElement, eventManager); + getViewElement().clearCards(); } @Override protected void initInteractions() { + getViewElement().getWeekField().setTextFormatter(new TextFormatter<>(change -> { + if (change.getControlNewText().matches("([0-9]*(\\.[0-9]*)?)?")) { + return change; + } + return null; + })); + + getViewElement().getWeekField().focusedProperty().addListener((observable, wasFocused, isNowFocused) -> { + if (!isNowFocused && getViewElement().getWeekField().getText().trim().isEmpty()) { + getViewElement().getWeekField().setText("1"); + } + filterData(getViewElement().getSearchField().getText(), Integer.parseInt(getViewElement().getWeekField().getText())); + }); + + getViewElement().getSearchField().textProperty().addListener((observable, oldValue, newValue) -> { + filterData(newValue, Integer.parseInt(getViewElement().getWeekField().getText())); + }); + } + + private void filterData(final String searchKeyword, final Integer weekTarget) { + getViewElement().clearCards(); + transactionArchive.getTransactions(weekTarget).forEach(t -> { + if (t.getShare().getStock().getCompany().toLowerCase().contains(searchKeyword.toLowerCase()) + || t.getShare().getStock().getSymbol().toLowerCase().contains(searchKeyword.toLowerCase())) { + String transactionType = "Purchase"; + String sharePrefix = "+ "; + String moneyPrefix = "- "; + + if(t.getClass().equals(Sale.class)){ + transactionType = "Sale"; + sharePrefix = "- "; + moneyPrefix = "+ "; + } + + getViewElement().addTransactionCard( + transactionType, + t.getShare().getStock().getSymbol(), + t.getShare().getStock().getCompany(), + sharePrefix + t.getShare().getQuantity().floatValue() + " shares", + moneyPrefix + t.getCalculator().calculateTotal().toString() + " NOK", + weekTarget.toString()); + } + }); } -} +} \ No newline at end of file diff --git a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/transactions/TransactionsView.java b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/transactions/TransactionsView.java index 5f60974..6d9f77a 100644 --- a/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/transactions/TransactionsView.java +++ b/src/main/java/edu/ntnu/idi/idatt2003/g40/mappe/view/widgets/transactions/TransactionsView.java @@ -1,21 +1,188 @@ package edu.ntnu.idi.idatt2003.g40.mappe.view.widgets.transactions; import edu.ntnu.idi.idatt2003.g40.mappe.view.ViewElement; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.control.TextField; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; import javafx.scene.layout.VBox; -public class TransactionsView extends ViewElement { +/** + * View for displaying a history of all transactions for the active player. + * + *

Extends {@link ViewElement}

+ * */ +public final class TransactionsView + extends ViewElement { + /** + * Search field. + * */ + private TextField searchField; + + /** + * Week input field. + * */ + private TextField weekField; + + /** + * Container element for cards. + * */ + private HBox cardsContainer; + + /** + * Entire search bar element. + * */ + private HBox searchBar; + + /** + * Search label text. + * */ + private Label searchLabel; + + /** + * Week label text. + * */ + private Label weekLabel; + + /** + * Scroll pane for cards. + * */ + private ScrollPane scrollPane; + + /** + * Constructor. + * + * @see ViewElement + * */ public TransactionsView() { super(new VBox(), TransactionsActions.class); } @Override protected void initLayout() { + searchBar = new HBox(); + searchLabel = new Label("Search:"); + searchField = new TextField(); + + HBox.setHgrow(searchField, Priority.ALWAYS); + weekLabel = new Label("Week:"); + weekField = new TextField("2"); + + searchBar.getChildren().addAll( + searchLabel, + searchField, + weekLabel, + weekField + ); + + // Horizontal scroll pane: + cardsContainer = new HBox(); + + scrollPane = new ScrollPane(cardsContainer); + scrollPane.setPannable(true); + + scrollPane.setVbarPolicy(ScrollPane.ScrollBarPolicy.NEVER); + + getRootPane().getChildren().addAll(searchBar, scrollPane); + } + + /** + * Method to add cards dynamically based on model data. + * + * @param type the type of transaction (PURCHASE/SALE). + * @param symbol the symbol of the stock this transaction was for. + * @param companyName name of the company behind the stock of this + * transaction. + * @param shares the amount of shares gained or lost during this + * transaction. + * @param nok the amount of money in NOK gained or lost during + * the transactions. + * @param week the week this transaction took place. + */ + public void addTransactionCard(final String type, + final String symbol, + final String companyName, + final String shares, + final String nok, + final String week) { + VBox card = new VBox(); + + // Header (SALE / PURCHASE) + Label typeLabel = new Label(type.toUpperCase()); + + // Company Details + Label companyLabel = new Label(symbol + ", " + companyName); + + // Info Rows (+- shares, +- NOK) + VBox infoBox = new VBox(); + + Label textRow1 = new Label(shares); + Label textRow2 = new Label(nok); + + infoBox.getChildren().addAll(textRow1, textRow2); + + Region spacer = new Region(); + VBox.setVgrow(spacer, Priority.ALWAYS); + + // Week Label + Label cardWeekLabel = new Label("Week " + week); + + card.getChildren().addAll( + typeLabel, + companyLabel, + infoBox, + spacer, + cardWeekLabel + ); + cardsContainer.getChildren().add(card); + + card.getStyleClass().add("transactions-transactionCard"); + typeLabel.getStyleClass().add("transactions-typeLabel"); + infoBox.getStyleClass().add("transactions-infoBox"); + companyLabel.getStyleClass().add("transactions-cardText"); + textRow1.getStyleClass().add("transactions-cardText"); + textRow2.getStyleClass().add("transactions-cardText"); + cardWeekLabel.getStyleClass().add("transactions-cardText"); + } + + /** + * Clears the displayed list of cards. + * */ + public void clearCards() { + cardsContainer.getChildren().clear(); + } + + /** + * Getter method for the search field. + * + * @return Search field. + * */ + public TextField getSearchField() { + return searchField; + } + + /** + * Getter method for the week filter field. + * + * @return week filter field. + * */ + public TextField getWeekField() { + return weekField; } @Override protected void initStyling() { - + getRootPane().getStyleClass().add("transactions-root"); + searchBar.getStyleClass().add("transactions-searchBar"); + searchLabel.getStyleClass().add("transactions-searchLabel"); + searchField.getStyleClass().add("transactions-searchField"); + weekLabel.getStyleClass().add("transactions-searchLabel"); + weekField.getStyleClass().add("transactions-weekField"); + scrollPane.getStyleClass().add("transactions-scrollPane"); + cardsContainer.getStyleClass().add("transactions-cardsContainer"); } -} +} \ No newline at end of file diff --git a/src/main/resources/styles.css b/src/main/resources/styles.css index a72733f..a6c00d5 100644 --- a/src/main/resources/styles.css +++ b/src/main/resources/styles.css @@ -1,5 +1,6 @@ .root { -fx-font-family: "Aptos"; + -fx-text-fill: black; } /* Container for the buttons */ @@ -563,3 +564,79 @@ -fx-text-fill: #555555; -fx-padding: 40; } + +/* ---------------- TRANSACTIONS VIEW ---------------- */ +.transactions-root { + -fx-spacing: 20; + -fx-padding: 15; + -fx-alignment: TOP_CENTER; +} + +.transactions-root .label { + -fx-text-fill: black; +} + +.transactions-searchBar { + -fx-spacing: 10; + -fx-alignment: CENTER_LEFT; + -fx-border-color: #000000; + -fx-border-width: 1.5; + -fx-background-color: #E0E0E0; + -fx-padding: 10; +} + +.transactions-searchLabel { + -fx-font-size: 14; +} + +.transactions-searchField { + -fx-background-color: white; + -fx-border-color: #CCCCCC; +} + +.transactions-weekField { + -fx-pref-width: 50; + -fx-alignment: CENTER; + -fx-background-color: white; + -fx-border-color: #000000; + -fx-border-width: 1.5; +} + +.transactions-transactionCard { + -fx-spacing: 15; + -fx-padding: 25; + -fx-alignment: TOP_CENTER; + -fx-pref-width: 260; + -fx-pref-height: 320; + -fx-background-color: #D6D6D6; + -fx-background-radius: 35; + -fx-border-color: #000000; + -fx-border-radius: 35; + -fx-border-width: 1.5; +} + +.transactions-typeLabel { + -fx-font-size: 28; + -fx-font-weight: bold; +} + +.transactions-infoBox { + -fx-spacing: 8; + -fx-alignment: CENTER; +} + +.transactions-cardText { + -fx-font-size: 14; +} + +.transactions-cardsContainer { + -fx-spacing: 25; + -fx-alignment: CENTER_LEFT; + -fx-padding: 10; +} + +.transactions-scrollPane { + -fx-fit-to-height: true; + -fx-background: transparent; + -fx-background-color: transparent; +} \ No newline at end of file