From d5f1554949321f2ebfda89efe39b0477a6ff2e55 Mon Sep 17 00:00:00 2001 From: Joe Carstairs Date: Sun, 8 Feb 2026 15:15:24 +0000 Subject: task-085: transactions view has transactions --- schist_desktop_gui/src/gui/components.rs | 2 + .../src/gui/components/account_navigation_entry.rs | 34 +++++++ .../src/gui/components/transactions_view.rs | 106 +++++++++------------ .../src/gui/screens/main_screen/main_screen.rs | 2 +- 4 files changed, 83 insertions(+), 61 deletions(-) create mode 100644 schist_desktop_gui/src/gui/components/account_navigation_entry.rs (limited to 'schist_desktop_gui/src/gui') 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> +{ + 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, - greeting: String, - navigation: Navigation, + navigation: Navigation, + transactions_by_account_id: HashMap>, } #[derive(Clone, Debug)] pub enum Message { - NavigationMessage(navigation::Message), + NavigationMessage(navigation::Message), SelectNextTransaction, SelectPrevTransaction, SetAccounts(Vec), @@ -31,13 +33,20 @@ pub enum Action { } impl TransactionsView { - pub fn new(accounts: Vec, 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, transactions: Vec) -> Self { + let account_navigation_entries: Vec = 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 = 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) -> Vec { - 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()), } -- cgit v1.2.3