Added account view, functional prototype for editing accounts.
This commit is contained in:
parent
23a0a20acb
commit
b1043c1624
2
pom.xml
2
pom.xml
|
@ -29,7 +29,7 @@
|
|||
<dependency>
|
||||
<groupId>com.andrewlalis</groupId>
|
||||
<artifactId>javafx-scene-router</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.3.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
package com.andrewlalis.perfin;
|
||||
|
||||
import com.andrewlalis.javafx_scene_router.SceneRouter;
|
||||
import com.andrewlalis.perfin.control.MainViewController;
|
||||
import com.andrewlalis.perfin.view.SplashScreenStage;
|
||||
import javafx.application.Application;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* The class from which the JavaFX-based application starts.
|
||||
|
@ -39,16 +37,14 @@ public class PerfinApp extends Application {
|
|||
|
||||
private void initMainScreen(Stage stage) {
|
||||
stage.hide();
|
||||
Scene mainViewScene = SceneUtil.load("/main-view.fxml", (Consumer<MainViewController>) c -> {
|
||||
c.mainContainer.setCenter(router.getViewPane());
|
||||
router.navigate("accounts");
|
||||
});
|
||||
Scene mainViewScene = SceneUtil.load("/main-view.fxml");
|
||||
stage.setScene(mainViewScene);
|
||||
stage.setTitle("Perfin");
|
||||
}
|
||||
|
||||
private static void defineRoutes() {
|
||||
router.map("accounts", SceneUtil.loadNode("/accounts-view.fxml"));
|
||||
router.map("edit-account", SceneUtil.loadNode("/edit-account.fxml"));
|
||||
router.map("accounts", PerfinApp.class.getResource("/accounts-view.fxml"));
|
||||
router.map("account", PerfinApp.class.getResource("/account-view.fxml"));
|
||||
router.map("edit-account", PerfinApp.class.getResource("/edit-account.fxml"));
|
||||
}
|
||||
}
|
|
@ -8,6 +8,8 @@ import javafx.scene.control.Label;
|
|||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import static com.andrewlalis.perfin.PerfinApp.router;
|
||||
|
||||
public class AccountTileController {
|
||||
private Account account;
|
||||
|
||||
|
@ -37,6 +39,7 @@ public class AccountTileController {
|
|||
accountNameLabel.setText(account.getName());
|
||||
container.addEventHandler(MouseEvent.MOUSE_CLICKED, event -> {
|
||||
System.out.println("Clicked on " + account.getAccountNumber());
|
||||
router.navigate("account", account);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package com.andrewlalis.perfin.control;
|
||||
|
||||
import com.andrewlalis.javafx_scene_router.RouteSelectionListener;
|
||||
import com.andrewlalis.perfin.model.Account;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class AccountViewController implements RouteSelectionListener {
|
||||
private Account account;
|
||||
|
||||
@FXML
|
||||
public Label titleLabel;
|
||||
@FXML
|
||||
public TextField accountNameField;
|
||||
@FXML
|
||||
public TextField accountNumberField;
|
||||
@FXML
|
||||
public TextField accountCreatedAtField;
|
||||
@FXML
|
||||
public TextField accountCurrencyField;
|
||||
|
||||
@Override
|
||||
public void onRouteSelected(Object context) {
|
||||
account = (Account) context;
|
||||
titleLabel.setText("Account: " + account.getAccountNumber());
|
||||
|
||||
accountNameField.setText(account.getName());
|
||||
accountNumberField.setText(account.getAccountNumber());
|
||||
accountCurrencyField.setText(account.getCurrency().getDisplayName());
|
||||
accountCreatedAtField.setText(account.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
|
||||
}
|
||||
}
|
|
@ -1,23 +1,23 @@
|
|||
package com.andrewlalis.perfin.control;
|
||||
|
||||
import com.andrewlalis.javafx_scene_router.RouteSelectionListener;
|
||||
import com.andrewlalis.perfin.SceneUtil;
|
||||
import com.andrewlalis.perfin.model.Account;
|
||||
import com.andrewlalis.perfin.model.Profile;
|
||||
import com.andrewlalis.perfin.view.BindingUtil;
|
||||
import javafx.application.Platform;
|
||||
import javafx.beans.property.SimpleListProperty;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.FlowPane;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class AccountsViewController {
|
||||
import static com.andrewlalis.perfin.PerfinApp.router;
|
||||
|
||||
public class AccountsViewController implements RouteSelectionListener {
|
||||
@FXML
|
||||
public BorderPane mainContainer;
|
||||
@FXML
|
||||
|
@ -47,17 +47,21 @@ public class AccountsViewController {
|
|||
noAccountsLabel.managedProperty().bind(noAccountsLabel.visibleProperty());
|
||||
accountsPane.visibleProperty().bind(listProp.emptyProperty().not());
|
||||
accountsPane.managedProperty().bind(accountsPane.visibleProperty());
|
||||
|
||||
// Populate the list of accounts once a profile is available.
|
||||
Profile.whenLoaded(profile -> {
|
||||
accountsList.setAll(profile.getDataSource().getAccountRepository().findAll());
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void createNewAccount() {
|
||||
Stage mainStage = (Stage) mainContainer.getScene().getWindow();
|
||||
Scene editAccountScene = SceneUtil.load("/edit-account.fxml");
|
||||
mainStage.setScene(editAccountScene);
|
||||
router.navigate("edit-account");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRouteSelected(Object context) {
|
||||
refreshAccounts();
|
||||
}
|
||||
|
||||
public void refreshAccounts() {
|
||||
Profile.whenLoaded(profile -> {
|
||||
accountsList.setAll(profile.getDataSource().getAccountRepository().findAll());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
package com.andrewlalis.perfin.control;
|
||||
|
||||
import com.andrewlalis.javafx_scene_router.RouteSelectionListener;
|
||||
import com.andrewlalis.perfin.model.Account;
|
||||
import com.andrewlalis.perfin.model.AccountType;
|
||||
import com.andrewlalis.perfin.model.Profile;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.ChoiceBox;
|
||||
import javafx.scene.control.ComboBox;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
|
||||
import java.util.Currency;
|
||||
|
||||
import static com.andrewlalis.perfin.PerfinApp.router;
|
||||
|
||||
public class EditAccountController implements RouteSelectionListener {
|
||||
private Account account;
|
||||
@FXML
|
||||
public Label titleLabel;
|
||||
@FXML
|
||||
public TextField accountNameField;
|
||||
@FXML
|
||||
public TextField accountNumberField;
|
||||
@FXML
|
||||
public ComboBox<Currency> accountCurrencyComboBox;
|
||||
@FXML
|
||||
public ChoiceBox<String> accountTypeChoiceBox;
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
final String[] currencies = {
|
||||
"USD",
|
||||
"EUR",
|
||||
"GBP"
|
||||
};
|
||||
for (String currencyCode : currencies) {
|
||||
accountCurrencyComboBox.getItems().add(Currency.getInstance(currencyCode));
|
||||
}
|
||||
accountCurrencyComboBox.getSelectionModel().select(Currency.getInstance("USD"));
|
||||
|
||||
accountTypeChoiceBox.getItems().add("Checking");
|
||||
accountTypeChoiceBox.getItems().add("Savings");
|
||||
accountTypeChoiceBox.getItems().add("Credit Card");
|
||||
accountTypeChoiceBox.getSelectionModel().select("Checking");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRouteSelected(Object context) {
|
||||
this.account = (Account) context;
|
||||
if (account == null) {
|
||||
titleLabel.setText("Editing New Account");
|
||||
} else {
|
||||
titleLabel.setText("Editing Account: " + account.getName());
|
||||
}
|
||||
resetForm();
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void save() {
|
||||
if (account == null) {
|
||||
// If we're editing a new account.
|
||||
String name = accountNameField.getText().strip();
|
||||
String number = accountNumberField.getText().strip();
|
||||
AccountType type = AccountType.parse(accountTypeChoiceBox.getValue());
|
||||
Currency currency = accountCurrencyComboBox.getValue();
|
||||
Account newAccount = new Account(type, number, name, currency);
|
||||
Profile.getCurrent().getDataSource().getAccountRepository().insert(newAccount);
|
||||
|
||||
// Once we create the new account, go to the account.
|
||||
router.getHistory().clear();
|
||||
router.navigate("accounts");
|
||||
} else {
|
||||
throw new IllegalStateException("Not implemented.");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void cancel() {
|
||||
router.navigateBack();
|
||||
}
|
||||
|
||||
public void resetForm() {
|
||||
if (account == null) {
|
||||
accountNameField.setText("");
|
||||
accountNumberField.setText("");
|
||||
accountTypeChoiceBox.getSelectionModel().selectFirst();
|
||||
accountCurrencyComboBox.getSelectionModel().select(Currency.getInstance("USD"));
|
||||
} else {
|
||||
// TODO: Set to original account.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
package com.andrewlalis.perfin.control;
|
||||
|
||||
import javafx.event.ActionEvent;
|
||||
import com.andrewlalis.perfin.view.BindingUtil;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.layout.BorderPane;
|
||||
import javafx.scene.layout.HBox;
|
||||
|
||||
|
@ -12,15 +13,30 @@ public class MainViewController {
|
|||
public BorderPane mainContainer;
|
||||
@FXML
|
||||
public HBox mainFooter;
|
||||
@FXML
|
||||
public HBox breadcrumbHBox;
|
||||
|
||||
@FXML
|
||||
public void goToAccounts() {
|
||||
public void initialize() {
|
||||
mainContainer.setCenter(router.getViewPane());
|
||||
BindingUtil.mapContent(
|
||||
breadcrumbHBox.getChildren(),
|
||||
router.getBreadCrumbs(),
|
||||
breadCrumb -> {
|
||||
Label label = new Label("> " + breadCrumb.route());
|
||||
if (breadCrumb.current()) {
|
||||
label.setStyle("-fx-font-weight: bold");
|
||||
}
|
||||
return label;
|
||||
}
|
||||
);
|
||||
|
||||
router.navigate("accounts");
|
||||
}
|
||||
|
||||
@FXML
|
||||
public void goToEditAccounts() {
|
||||
router.navigate("edit-account");
|
||||
public void goToAccounts() {
|
||||
router.navigate("accounts");
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
|
|
@ -47,4 +47,12 @@ public class Account {
|
|||
public Currency getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,5 +3,15 @@ package com.andrewlalis.perfin.model;
|
|||
public enum AccountType {
|
||||
CHECKING,
|
||||
SAVINGS,
|
||||
CREDIT_CARD
|
||||
CREDIT_CARD;
|
||||
|
||||
public static AccountType parse(String s) {
|
||||
s = s.strip().toUpperCase();
|
||||
return switch (s) {
|
||||
case "CHECKING" -> CHECKING;
|
||||
case "SAVINGS" -> SAVINGS;
|
||||
case "CREDIT CARD", "CREDITCARD" -> CREDIT_CARD;
|
||||
default -> throw new IllegalArgumentException("Invalid AccountType string: " + s);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<BorderPane
|
||||
xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="com.andrewlalis.perfin.control.AccountViewController"
|
||||
stylesheets="@style/account-view.css"
|
||||
styleClass="main-container"
|
||||
>
|
||||
<top>
|
||||
<Label fx:id="titleLabel"/>
|
||||
</top>
|
||||
<center>
|
||||
<VBox>
|
||||
<VBox styleClass="account-property-box">
|
||||
<Label text="Name"/>
|
||||
<TextField fx:id="accountNameField" editable="false"/>
|
||||
</VBox>
|
||||
<VBox styleClass="account-property-box">
|
||||
<Label text="Number"/>
|
||||
<TextField fx:id="accountNumberField" editable="false"/>
|
||||
</VBox>
|
||||
<VBox styleClass="account-property-box">
|
||||
<Label text="Currency"/>
|
||||
<TextField fx:id="accountCurrencyField" editable="false"/>
|
||||
</VBox>
|
||||
<VBox styleClass="account-property-box">
|
||||
<Label text="Created At"/>
|
||||
<TextField fx:id="accountCreatedAtField" editable="false"/>
|
||||
</VBox>
|
||||
</VBox>
|
||||
</center>
|
||||
</BorderPane>
|
|
@ -2,32 +2,39 @@
|
|||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
|
||||
<BorderPane xmlns="http://javafx.com/javafx/17.0.2-ea" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<BorderPane
|
||||
xmlns="http://javafx.com/javafx/17.0.2-ea"
|
||||
xmlns:fx="http://javafx.com/fxml/1"
|
||||
fx:controller="com.andrewlalis.perfin.control.EditAccountController"
|
||||
stylesheets="@style/edit-account.css"
|
||||
styleClass="main-container"
|
||||
>
|
||||
<top>
|
||||
<Label text="Edit Account"/>
|
||||
<Label fx:id="titleLabel" text="Edit Account"/>
|
||||
</top>
|
||||
<center>
|
||||
<GridPane BorderPane.alignment="CENTER">
|
||||
<GridPane BorderPane.alignment="CENTER" styleClass="fields-grid">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="NEVER" minWidth="10.0" />
|
||||
<ColumnConstraints hgrow="ALWAYS" minWidth="10.0" />
|
||||
</columnConstraints>
|
||||
<Label GridPane.columnIndex="0" GridPane.rowIndex="0" text="Name"/>
|
||||
<TextField GridPane.columnIndex="1" GridPane.rowIndex="0" text="Bleh"/>
|
||||
<TextField fx:id="accountNameField" GridPane.columnIndex="1" GridPane.rowIndex="0" text="Bleh"/>
|
||||
|
||||
<Label GridPane.columnIndex="0" GridPane.rowIndex="1" text="Account Number"/>
|
||||
<TextField GridPane.columnIndex="1" GridPane.rowIndex="1" text="1234"/>
|
||||
<TextField fx:id="accountNumberField" GridPane.columnIndex="1" GridPane.rowIndex="1" text="1234"/>
|
||||
|
||||
<Label GridPane.columnIndex="0" GridPane.rowIndex="2" text="Currency"/>
|
||||
<ChoiceBox GridPane.columnIndex="1" GridPane.rowIndex="2">
|
||||
</ChoiceBox>
|
||||
<ComboBox fx:id="accountCurrencyComboBox" GridPane.columnIndex="1" GridPane.rowIndex="2"/>
|
||||
|
||||
<Label GridPane.columnIndex="0" GridPane.rowIndex="3" text="Account Type"/>
|
||||
<ChoiceBox fx:id="accountTypeChoiceBox" GridPane.columnIndex="1" GridPane.rowIndex="3"/>
|
||||
</GridPane>
|
||||
</center>
|
||||
<bottom>
|
||||
<FlowPane BorderPane.alignment="CENTER_RIGHT">
|
||||
<Button text="Save" />
|
||||
<Button text="Cancel" />
|
||||
<Button text="Save" onAction="#save"/>
|
||||
<Button text="Cancel" onAction="#cancel"/>
|
||||
</FlowPane>
|
||||
</bottom>
|
||||
</BorderPane>
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.scene.control.*?>
|
||||
<?import javafx.scene.layout.BorderPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.*?>
|
||||
<BorderPane
|
||||
xmlns="http://javafx.com/javafx"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
|
@ -11,13 +10,16 @@
|
|||
stylesheets="@style/main-view.css"
|
||||
>
|
||||
<top>
|
||||
<VBox>
|
||||
<HBox fx:id="mainHeader">
|
||||
<Label text="TODO: Add breadcrumb navigation/header here!"/>
|
||||
<Button text="Back" onAction="#goBack"/>
|
||||
<Button text="Forward" onAction="#goForward"/>
|
||||
<Button text="Go to accounts!" onAction="#goToAccounts"/>
|
||||
<Button text="Go to edit accounts!" onAction="#goToEditAccounts"/>
|
||||
<Button text="Accounts" onAction="#goToAccounts"/>
|
||||
</HBox>
|
||||
<HBox fx:id="breadcrumbHBox"/>
|
||||
<Separator/>
|
||||
</VBox>
|
||||
|
||||
</top>
|
||||
<bottom>
|
||||
<HBox fx:id="mainFooter" spacing="5">
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
.main-container {
|
||||
-fx-padding: 5px;
|
||||
}
|
||||
|
||||
#titleLabel {
|
||||
-fx-font-weight: bold;
|
||||
-fx-font-size: large;
|
||||
}
|
||||
|
||||
.account-property-box {
|
||||
-fx-padding: 5px 0 5px 0;
|
||||
-fx-spacing: 3px;
|
||||
}
|
||||
|
||||
.account-property-box > Label {
|
||||
-fx-font-weight: bold;
|
||||
}
|
||||
|
||||
.account-property-box > TextField {
|
||||
-fx-min-width: 200px;
|
||||
}
|
||||
|
||||
#accountNumberField {
|
||||
-fx-font-family: monospace;
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
.main-container {
|
||||
-fx-padding: 5px;
|
||||
}
|
||||
|
||||
.fields-grid {
|
||||
-fx-hgap: 3px;
|
||||
-fx-vgap: 3px;
|
||||
-fx-padding: 5px;
|
||||
}
|
||||
|
||||
#titleLabel {
|
||||
-fx-font-size: large;
|
||||
-fx-font-weight: bold;
|
||||
}
|
|
@ -1,5 +1,11 @@
|
|||
#mainHeader {
|
||||
-fx-padding: 3px;
|
||||
-fx-spacing: 3px;
|
||||
}
|
||||
|
||||
#breadcrumbHBox {
|
||||
-fx-spacing: 3px;
|
||||
-fx-font-size: small;
|
||||
}
|
||||
|
||||
#mainFooter {
|
||||
|
|
Loading…
Reference in New Issue