summaryrefslogtreecommitdiff
path: root/schist_desktop_gui
diff options
context:
space:
mode:
authorJoe Carstairs <me@joeac.net>2026-02-08 15:15:24 +0000
committerJoe Carstairs <me@joeac.net>2026-02-08 15:15:24 +0000
commitd5f1554949321f2ebfda89efe39b0477a6ff2e55 (patch)
tree0fbb780f8df2c4c742c0b602febacd2a2d9684c8 /schist_desktop_gui
parentd21a2500813b3fea4892fff9dbbf572e37b5d70d (diff)
task-085: transactions view has transactions
Diffstat (limited to 'schist_desktop_gui')
-rw-r--r--schist_desktop_gui/src/gui/components.rs2
-rw-r--r--schist_desktop_gui/src/gui/components/account_navigation_entry.rs34
-rw-r--r--schist_desktop_gui/src/gui/components/transactions_view.rs106
-rw-r--r--schist_desktop_gui/src/gui/screens/main_screen/main_screen.rs2
4 files changed, 83 insertions, 61 deletions
diff --git a/schist_desktop_gui/src/gui/components.rs b/schist_desktop_gui/src/gui/components.rs
index bb5590f..606c418 100644
--- a/schist_desktop_gui/src/gui/components.rs
+++ b/schist_desktop_gui/src/gui/components.rs
@@ -1,3 +1,4 @@
+mod account_navigation_entry;
pub mod balances_view;
pub mod bucket_navigation_entry;
pub mod buckets_view;
@@ -7,6 +8,7 @@ pub mod panel;
pub mod text;
pub mod transactions_view;
+pub use account_navigation_entry::AccountNavigationEntry;
pub use balances_view::BalancesView;
pub use bucket_navigation_entry::BucketNavigationEntry;
pub use buckets_view::BucketsView;
diff --git a/schist_desktop_gui/src/gui/components/account_navigation_entry.rs b/schist_desktop_gui/src/gui/components/account_navigation_entry.rs
new file mode 100644
index 0000000..6a582a7
--- /dev/null
+++ b/schist_desktop_gui/src/gui/components/account_navigation_entry.rs
@@ -0,0 +1,34 @@
+use iced::Element;
+use schist_models::Account;
+
+use crate::{
+ gui::components::{navigation, Text},
+ impl_focusable,
+};
+
+#[derive(Clone, Debug, PartialEq)]
+pub struct AccountNavigationEntry {
+ pub account: Account,
+ is_focused: bool,
+}
+
+impl AccountNavigationEntry {
+ pub fn new(account: Account) -> Self {
+ Self {
+ account,
+ is_focused: false,
+ }
+ }
+}
+
+impl<'a> From<&'a AccountNavigationEntry>
+ for Element<'a, navigation::Message<AccountNavigationEntry>>
+{
+ fn from(account_navigation_entry: &'a AccountNavigationEntry) -> Self {
+ Text::default(&account_navigation_entry.account.name)
+ .highlight_maybe(account_navigation_entry.is_focused)
+ .into()
+ }
+}
+
+impl_focusable!(AccountNavigationEntry);
diff --git a/schist_desktop_gui/src/gui/components/transactions_view.rs b/schist_desktop_gui/src/gui/components/transactions_view.rs
index 1cb569c..59d7ae3 100644
--- a/schist_desktop_gui/src/gui/components/transactions_view.rs
+++ b/schist_desktop_gui/src/gui/components/transactions_view.rs
@@ -1,26 +1,28 @@
+use std::collections::HashMap;
+
use iced::{
alignment,
widget::{column, row, Container},
Element, Length,
};
-use schist_models::Account;
+use itertools::Itertools;
+use schist_models::{Account, Transaction};
use crate::{
- gui::components::{navigation, Navigation, Text},
+ gui::components::{navigation, AccountNavigationEntry, Navigation, Text},
style::SPACING_LG,
traits::{Component, Viewable},
};
#[derive(Clone, Debug)]
pub struct TransactionsView {
- accounts: Vec<Account>,
- greeting: String,
- navigation: Navigation<Text>,
+ navigation: Navigation<AccountNavigationEntry>,
+ transactions_by_account_id: HashMap<i32, Vec<Transaction>>,
}
#[derive(Clone, Debug)]
pub enum Message {
- NavigationMessage(navigation::Message<Text>),
+ NavigationMessage(navigation::Message<AccountNavigationEntry>),
SelectNextTransaction,
SelectPrevTransaction,
SetAccounts(Vec<Account>),
@@ -31,13 +33,20 @@ pub enum Action {
}
impl TransactionsView {
- pub fn new(accounts: Vec<Account>, greeting: &str) -> Self {
- let account_names = view_account_names(accounts.clone());
- let navigation = Navigation::new(account_names.clone().first().cloned(), account_names);
+ pub fn new(accounts: Vec<Account>, transactions: Vec<Transaction>) -> Self {
+ let account_navigation_entries: Vec<AccountNavigationEntry> = accounts
+ .into_iter()
+ .map(AccountNavigationEntry::new)
+ .collect();
+ let navigation = Navigation::new(
+ account_navigation_entries.first().cloned(),
+ account_navigation_entries,
+ );
Self {
- accounts: accounts,
- greeting: greeting.to_owned(),
navigation: navigation,
+ transactions_by_account_id: transactions
+ .into_iter()
+ .into_group_map_by(|t| t.account_id),
}
}
}
@@ -45,7 +54,20 @@ impl TransactionsView {
impl<'a> Viewable<'a, Message> for TransactionsView {
fn view(&'a self) -> Element<'a, Message> {
let navigation = self.navigation.view().map(Message::NavigationMessage);
- let main_content = column![Text::default(&self.greeting).as_element()];
+ let main_content = column![
+ Text::default("Hello, transactions!").as_element(),
+ Text::default(&format!(
+ "{} transactions in this account.",
+ self.navigation.active_option.clone().map_or(
+ 0,
+ |AccountNavigationEntry { account, .. }| self
+ .transactions_by_account_id
+ .get(&account.id)
+ .map_or(0, |transactions| transactions.len())
+ )
+ ))
+ .as_element(),
+ ];
row![
Container::new(navigation).width(Length::FillPortion(1)),
Container::new(main_content).width(Length::FillPortion(3)),
@@ -61,62 +83,26 @@ impl<'a> Component<'a, Message, Action> for TransactionsView {
fn update(&mut self, message: Message) -> Action {
match message {
Message::NavigationMessage(message) => {
- match self.navigation.update(message) {
- navigation::Action::ActivateOption(group_name)
- | navigation::Action::SelectOption(group_name) => {
- self.greeting = make_greeting(group_name);
- Action::None
- }
- navigation::Action::None => Action::None,
- };
+ self.navigation.update(message);
Action::None
}
Message::SetAccounts(accounts) => {
- self.accounts = accounts.clone();
- match self
- .navigation
- .update(navigation::Message::SetOptions(view_account_names(
- accounts,
- ))) {
- navigation::Action::ActivateOption(option)
- | navigation::Action::SelectOption(option) => {
- self.greeting = make_greeting(option);
- Action::None
- }
- navigation::Action::None => Action::None,
- }
+ let account_navigation_entries: Vec<AccountNavigationEntry> = accounts
+ .into_iter()
+ .map(AccountNavigationEntry::new)
+ .collect();
+ self.navigation
+ .update(navigation::Message::SetOptions(account_navigation_entries));
+ Action::None
}
Message::SelectNextTransaction => {
- match self.navigation.update(navigation::Message::SelectNext) {
- navigation::Action::ActivateOption(option)
- | navigation::Action::SelectOption(option) => {
- self.greeting = make_greeting(option);
- Action::None
- }
- navigation::Action::None => Action::None,
- }
+ self.navigation.update(navigation::Message::SelectNext);
+ Action::None
}
Message::SelectPrevTransaction => {
- match self.navigation.update(navigation::Message::SelectPrev) {
- navigation::Action::ActivateOption(option)
- | navigation::Action::SelectOption(option) => {
- self.greeting = make_greeting(option);
- Action::None
- }
- navigation::Action::None => Action::None,
- }
+ self.navigation.update(navigation::Message::SelectPrev);
+ Action::None
}
}
}
}
-
-fn make_greeting(account_name: Text) -> String {
- format!("Hello, {} account!", account_name.content)
-}
-
-fn view_account_names(accounts: Vec<Account>) -> Vec<Text> {
- accounts
- .iter()
- .map(|acc| Text::new(acc.name.as_str()))
- .collect()
-}
diff --git a/schist_desktop_gui/src/gui/screens/main_screen/main_screen.rs b/schist_desktop_gui/src/gui/screens/main_screen/main_screen.rs
index 5ed4b30..e526dc5 100644
--- a/schist_desktop_gui/src/gui/screens/main_screen/main_screen.rs
+++ b/schist_desktop_gui/src/gui/screens/main_screen/main_screen.rs
@@ -197,7 +197,7 @@ impl MainScreen {
balances_view: BalancesView::new(Vec::new()),
buckets: Vec::new(),
buckets_view: BucketsView::new(Vec::new(), "Hello, buckets!"),
- transactions_view: TransactionsView::new(Vec::new(), "Hello, transactions!"),
+ transactions_view: TransactionsView::new(Vec::new(), Vec::new()),
active_view: View::Balances,
view_navigation: Navigation::new(Some(View::Balances), View::views()),
}