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 --- .../src/gui/components/account_navigation_entry.rs | 34 +++++++ .../src/gui/components/transactions_view.rs | 106 +++++++++------------ 2 files changed, 80 insertions(+), 60 deletions(-) create mode 100644 schist_desktop_gui/src/gui/components/account_navigation_entry.rs (limited to 'schist_desktop_gui/src/gui/components') 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() -} -- cgit v1.2.3