mod view_transactions_view; use std::collections::HashMap; use itertools::Itertools; use schist_models::{Account, Transaction}; use crate::{ gui::components::{navigation, table, AccountNavigationEntry, Navigation, Table}, traits::Component, }; #[derive(Clone, Debug)] pub struct TransactionsView { navigation: Navigation, table: Table, transactions_by_account_id: HashMap>, } #[derive(Clone, Debug)] pub enum Message { NavigationMessage(navigation::Message), SelectNextAccount, SelectPrevAccount, SetAccounts(Vec), SetTransactions(Vec), TableMessage(table::Message), } pub enum Action { None, } impl TransactionsView { pub fn new(accounts: &[Account], transactions: &[Transaction]) -> Self { let account_navigation_entries: Vec = accounts .iter() .cloned() .map(AccountNavigationEntry::new) .collect(); let navigation = Navigation::new( account_navigation_entries.first().cloned(), account_navigation_entries, ); let mut transactions_view = Self { navigation: navigation, table: Table::default(), transactions_by_account_id: transactions .into_iter() .cloned() .into_group_map_by(|t| t.account_id), }; transactions_view.refresh_table(); transactions_view } fn refresh_table(&mut self) { self.table = Table { cols: vec![ table::Column::new(0, "Date"), table::Column::new(1, "Bucket"), table::Column::new(2, "Payee"), table::Column::new(3, "Quantity"), table::Column::new(4, "Balance"), ], rows: self.navigation.active_option.clone().map_or_else( Vec::new, |AccountNavigationEntry { account, .. }| { self.transactions_by_account_id .get(&account.id) .cloned() .unwrap_or_else(Vec::new) .iter() .map(|t| { HashMap::from([ (0, table::Value::String(t.date.to_string())), ( 1, table::Value::String(t.bucket_id.map_or_else( || String::from("None"), |id| id.to_string(), )), ), (2, table::Value::String(t.counterparty.clone())), (3, table::Value::Currency(t.amount)), (4, table::Value::String(String::from("TODO"))), ]) }) .collect() }, ), }; } } impl<'a> Component<'a, Message, Action> for TransactionsView { fn update(&mut self, message: Message) -> Action { match message { Message::NavigationMessage(message) => self.update_navigation(message), Message::SetAccounts(accounts) => { let account_navigation_entries: Vec = accounts .into_iter() .map(AccountNavigationEntry::new) .collect(); self.update_navigation(navigation::Message::SetOptions(account_navigation_entries)) } Message::SetTransactions(transactions) => { self.transactions_by_account_id = transactions.into_iter().into_group_map_by(|t| t.account_id); self.refresh_table(); Action::None } Message::SelectNextAccount => self.update_navigation(navigation::Message::SelectNext), Message::SelectPrevAccount => self.update_navigation(navigation::Message::SelectPrev), } } } impl TransactionsView { fn update_navigation( &mut self, message: navigation::Message, ) -> Action { match self.navigation.update(message) { navigation::Action::ActivateOption(_) | navigation::Action::SelectOption(_) => { self.refresh_table(); Action::None } navigation::Action::None => Action::None, } } }