mod view_transactions_view; use std::{collections::HashMap, mem::transmute}; use itertools::Itertools; use schist_models::{Account, Bucket, Transaction}; use crate::{ gui::components::{navigation, AccountNavigationEntry, Navigation}, traits::Component, }; #[derive(Clone, Debug)] pub struct TransactionsView { account_balances_by_transaction_id: HashMap, buckets: Vec, navigation: Navigation, transactions_by_account_id: HashMap>, } #[derive(Clone, Debug)] pub enum Message { NavigationMessage(navigation::Message), SelectNextAccount, SelectPrevAccount, SetAccounts(Vec), SetBuckets(Vec), SetTransactions(Vec), } pub enum Action { None, } impl TransactionsView { pub fn new(accounts: &[Account], buckets: &[Bucket], 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 { account_balances_by_transaction_id: HashMap::with_capacity(transactions.len()), buckets: buckets.to_vec(), navigation: navigation, transactions_by_account_id: HashMap::with_capacity(accounts.len()), }; transactions_view.set_transactions(transactions); transactions_view } fn set_transactions(&mut self, transactions: &[Transaction]) { self.transactions_by_account_id = transactions .into_iter() .cloned() .into_group_map_by(|t| t.account_id); self.account_balances_by_transaction_id = HashMap::new(); for entry in self.transactions_by_account_id.iter_mut() { entry.1.sort_by(|t1, t2| t2.date.cmp(&t1.date)); let mut running_balance = 0; for transaction in entry.1.iter().rev() { running_balance += transaction.amount; self.account_balances_by_transaction_id .insert(transaction.id, running_balance); } } } } 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::SetBuckets(buckets) => { self.buckets = buckets; Action::None } Message::SetTransactions(transactions) => { self.set_transactions(&transactions); 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(_) => { Action::None } navigation::Action::None => Action::None, } } }