From 91f43092c3624d8321b5860690d0aeece0d69d49 Mon Sep 17 00:00:00 2001 From: thatscringebro Date: Wed, 18 Mar 2026 11:12:16 -0400 Subject: [PATCH] tabs --- src/app.rs | 20 ++++++++++++ src/main.rs | 12 +++++++ src/ui.rs | 91 +++++++++++++++++++++++++++++++++-------------------- 3 files changed, 89 insertions(+), 34 deletions(-) diff --git a/src/app.rs b/src/app.rs index 6e18450..f3689a6 100644 --- a/src/app.rs +++ b/src/app.rs @@ -14,6 +14,8 @@ pub struct App { pub selected_account_input: AccountInput, pub current_input: String, pub tr_types: Vec, + pub selected_tab: usize, + pub tabs: Vec, pub connection: Connection, } @@ -40,6 +42,14 @@ impl App { selected_account_input: AccountInput::Asset, current_input: String::new(), tr_types: data_layer::get_transaction_types(&con), + selected_tab: 0, + tabs: [ + "Transactions".to_string(), + "Chart".to_string(), + "Chart 2".to_string(), + "Chart 3".to_string(), + ] + .to_vec(), connection: con, }; } @@ -258,4 +268,14 @@ impl App { } } } + pub fn next_tab(&mut self) { + if self.selected_tab < self.tabs.len() { + self.selected_tab += 1; + } + } + pub fn previous_tab(&mut self) { + if self.selected_tab > 0 { + self.selected_tab -= 1; + } + } } diff --git a/src/main.rs b/src/main.rs index fe8803e..edf41e3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -90,6 +90,18 @@ where app.previous_tr(); } }, + KeyCode::Char('l') => match app.current_widget { + CurrentWidget::AccountList => {} + CurrentWidget::TrxList => { + app.next_tab(); + } + }, + KeyCode::Char('h') => match app.current_widget { + CurrentWidget::AccountList => {} + CurrentWidget::TrxList => { + app.previous_tab(); + } + }, KeyCode::Char('n') => match app.current_widget { CurrentWidget::AccountList => { app.current_screen = CurrentScreen::NewAccount; diff --git a/src/ui.rs b/src/ui.rs index ffef474..bef89e5 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -3,7 +3,7 @@ use ratatui::{ Frame, layout::{Constraint, Direction, Layout, Rect}, style::{Color, Modifier, Style, palette::tailwind::SLATE}, - text::{Line, Text}, + text::{Line, Span, Text}, widgets::{ Block, Borders, Clear, HighlightSpacing, List, ListItem, Paragraph, Row, StatefulWidget, Table, Wrap, @@ -32,6 +32,7 @@ pub fn ui(frame: &mut Frame, app: &mut App) { .borders(Borders::ALL) .border_style(Style::new().fg(Color::DarkGray)); let mut trx_block = Block::default() + .title(build_tab_title(app.selected_tab, app.tabs.clone())) .borders(Borders::ALL) .border_style(Style::new().fg(Color::DarkGray)); @@ -68,40 +69,43 @@ pub fn ui(frame: &mut Frame, app: &mut App) { }; frame.render_widget(Paragraph::new(info).block(info_block), right_layout[0]); - let trx_header = Row::new(["Date", "Type", "Amount", "Description"]); - let trx_rows = app.get_list_trx().into_iter().map(|tr| { - Row::new([ - tr.get_date().format("%Y-%m-%d").to_string(), - tr.get_type().get_description(), - tr.get_amount().to_string(), - tr.get_desc(), - ]) - .style(Style::new().fg(if tr.get_amount() > 0.0 { - Color::Green - } else { - Color::Red - })) - }); - let widths = [ - Constraint::Percentage(30), - Constraint::Percentage(20), - Constraint::Percentage(20), - Constraint::Percentage(50), - ]; - let trx_table = Table::new(trx_rows, widths) - .block(trx_block) - .header(trx_header) - .row_highlight_style(SELECTED_STYLE) - .highlight_symbol(">") - .highlight_spacing(HighlightSpacing::Always) - .column_spacing(1); + if app.selected_tab == 0 { + let trx_header = Row::new(["Date", "Type", "Amount", "Description"]); + let trx_rows = app.get_list_trx().into_iter().map(|tr| { + Row::new([ + tr.get_date().format("%Y-%m-%d").to_string(), + tr.get_type().get_description(), + tr.get_amount().to_string(), + tr.get_desc(), + ]) + .style(Style::new().fg(if tr.get_amount() > 0.0 { + Color::Green + } else { + Color::Red + })) + }); + let widths = [ + Constraint::Percentage(30), + Constraint::Percentage(20), + Constraint::Percentage(20), + Constraint::Percentage(50), + ]; + let trx_table = Table::new(trx_rows, widths) + .block(trx_block) + .header(trx_header) + .row_highlight_style(SELECTED_STYLE) + .highlight_symbol(">") + .highlight_spacing(HighlightSpacing::Always) + .column_spacing(1); - StatefulWidget::render( - trx_table, - right_layout[1], - frame.buffer_mut(), - &mut app.trx_table.state, - ); + StatefulWidget::render( + trx_table, + right_layout[1], + frame.buffer_mut(), + &mut app.trx_table.state, + ); + } else if app.selected_tab == 1 { + } if let CurrentScreen::NewAccount = app.current_screen { let popup = Block::default() @@ -314,6 +318,25 @@ fn ac_input_str(input: AccountInput, app: &mut App) -> String { AccountInput::Asset => app.new_account.get_asset_price().to_string(), } } +fn build_tab_title(selected: usize, labels: Vec) -> Vec> { + let mut spans = Vec::new(); + + for (i, label) in labels.iter().enumerate() { + let style = if i == selected { + Style::new().fg(Color::Magenta) + } else { + Style::new() + }; + + spans.push(Span::raw(label.clone()).style(style)); + + if i + 1 < labels.len() { + spans.push(Span::raw(" | ").style(Style::new().fg(Color::DarkGray))); + } + } + + return spans; +} impl From<&Account> for ListItem<'_> { fn from(value: &Account) -> Self { let line = Line::styled(