feat: Added history tab, and event passing
This commit is contained in:
parent
6ef492ee10
commit
7d1613b0c8
7 changed files with 327 additions and 138 deletions
135
src/app.rs
135
src/app.rs
|
@ -1,53 +1,134 @@
|
||||||
|
|
||||||
|
use crossterm::event::{Event, self, KeyCode};
|
||||||
|
use ratatui::widgets::ListState;
|
||||||
|
|
||||||
|
use crate::uis::history::HistoryState;
|
||||||
use crate::uis::new_transaction::NewTransactionTabState;
|
use crate::uis::new_transaction::NewTransactionTabState;
|
||||||
|
use crate::uis::navigation_frame::NavigationState;
|
||||||
|
|
||||||
pub type AppResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
pub type AppResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||||
|
|
||||||
pub enum FocusedBlock {
|
pub struct StatefulList<T> {
|
||||||
Navigation,
|
pub state: ListState,
|
||||||
Body,
|
pub items: Vec<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> StatefulList<T> {
|
||||||
|
pub fn with_items(items: Vec<T>) -> StatefulList<T> {
|
||||||
|
StatefulList {
|
||||||
|
state: ListState::default(),
|
||||||
|
items,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&mut self) {
|
||||||
|
let i = match self.state.selected() {
|
||||||
|
Some(i) => {
|
||||||
|
if i >= self.items.len() - 1 {
|
||||||
|
0
|
||||||
|
} else {
|
||||||
|
i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
self.state.select(Some(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn previous(&mut self) {
|
||||||
|
let i = match self.state.selected() {
|
||||||
|
Some(i) => {
|
||||||
|
if i == 0 {
|
||||||
|
self.items.len() - 1
|
||||||
|
} else {
|
||||||
|
i - 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => 0,
|
||||||
|
};
|
||||||
|
self.state.select(Some(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unselect(&mut self) {
|
||||||
|
self.state.select(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum InputMode {
|
||||||
|
Insert,
|
||||||
|
Normal,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct App<'a> {
|
pub struct App<'a> {
|
||||||
pub running: bool,
|
pub running: bool,
|
||||||
pub tabs: Vec<&'a str>,
|
|
||||||
pub tab_index: usize,
|
|
||||||
pub focus: FocusedBlock,
|
|
||||||
|
|
||||||
pub new_transaction_tab_state: NewTransactionTabState<'a>,
|
pub states: States<'a>,
|
||||||
|
|
||||||
|
pub input_mode: InputMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> App<'a> {
|
impl<'a> App<'a> {
|
||||||
pub fn new() -> App<'a> {
|
pub fn new() -> App<'a> {
|
||||||
App {
|
App {
|
||||||
running: true,
|
running: true,
|
||||||
|
states: States::new(),
|
||||||
tabs: vec!["History", "Tab2", "Tab3"],
|
input_mode: InputMode::Normal,
|
||||||
tab_index: 0,
|
|
||||||
focus: FocusedBlock::Navigation,
|
|
||||||
|
|
||||||
new_transaction_tab_state: NewTransactionTabState::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_tab(&mut self) {
|
pub fn poll_events(&mut self) -> AppResult<()> {
|
||||||
self.tab_index = (self.tab_index + 1) % self.tabs.len();
|
if let Event::Key(key) = event::read()? {
|
||||||
}
|
// 'q' needs to be handled at the top level so it can't be
|
||||||
|
// accidentally handed to a dead end
|
||||||
pub fn prev_tab(&mut self) {
|
if let KeyCode::Char('q') = key.code {
|
||||||
if self.tab_index > 0 {
|
if let Some(_) = self.states.nav_state.message.clone() {
|
||||||
self.tab_index -= 1;
|
self.states.nav_state.message = None;
|
||||||
} else {
|
} else {
|
||||||
self.tab_index = self.tabs.len() - 1;
|
if let ActiveFrame::Navigation = self.states.active_frame {
|
||||||
|
self.running = false;
|
||||||
|
} else {
|
||||||
|
self.states.active_frame = ActiveFrame::Navigation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn focus_navigation(&mut self) {
|
|
||||||
self.focus = FocusedBlock::Navigation;
|
|
||||||
}
|
}
|
||||||
|
match self.states.active_frame {
|
||||||
pub fn focus_body(&mut self) {
|
ActiveFrame::Navigation => {
|
||||||
self.focus = FocusedBlock::Body;
|
NavigationState::handle_event(key, self);
|
||||||
|
}
|
||||||
|
ActiveFrame::History => {
|
||||||
|
HistoryState::handle_event(key, self);
|
||||||
|
}
|
||||||
|
ActiveFrame::NewTransaction => {
|
||||||
|
NewTransactionTabState::handle_event(key, self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ActiveFrame {
|
||||||
|
Navigation,
|
||||||
|
NewTransaction,
|
||||||
|
History,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct States<'a> {
|
||||||
|
pub nav_state: NavigationState<'a>,
|
||||||
|
pub transactions: NewTransactionTabState<'a>,
|
||||||
|
pub history: HistoryState,
|
||||||
|
|
||||||
|
pub active_frame: ActiveFrame,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> States<'a> {
|
||||||
|
pub fn new() -> States<'a> {
|
||||||
|
States {
|
||||||
|
nav_state: NavigationState::new(),
|
||||||
|
transactions: NewTransactionTabState::new(),
|
||||||
|
history: HistoryState::new(),
|
||||||
|
|
||||||
|
active_frame: ActiveFrame::Navigation,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
32
src/main.rs
32
src/main.rs
|
@ -7,9 +7,8 @@ use ratatui::{
|
||||||
Terminal,
|
Terminal,
|
||||||
};
|
};
|
||||||
|
|
||||||
use recount::app::{App, AppResult, FocusedBlock};
|
use recount::app::{App, AppResult};
|
||||||
use recount::tui::Tui;
|
use recount::tui::Tui;
|
||||||
use recount::uis::new_transaction::NewTransactionTabState;
|
|
||||||
|
|
||||||
fn main() -> AppResult<()> {
|
fn main() -> AppResult<()> {
|
||||||
// Create an application.
|
// Create an application.
|
||||||
|
@ -28,34 +27,7 @@ fn main() -> AppResult<()> {
|
||||||
tui.draw(&mut app)?;
|
tui.draw(&mut app)?;
|
||||||
|
|
||||||
// Handle events.
|
// Handle events.
|
||||||
if let Event::Key(key) = event::read()? {
|
app.poll_events()?;
|
||||||
match app.focus {
|
|
||||||
FocusedBlock::Body => {
|
|
||||||
match app.tab_index {
|
|
||||||
2 => {
|
|
||||||
NewTransactionTabState::handle_event(key, &mut app);
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
// Work around "You entered an empty body, and now, I am dead" loops
|
|
||||||
app.focus_navigation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
FocusedBlock::Navigation => {
|
|
||||||
if key.kind == KeyEventKind::Press {
|
|
||||||
match key.code {
|
|
||||||
KeyCode::Char('q') => break,
|
|
||||||
KeyCode::Tab => app.next_tab(),
|
|
||||||
KeyCode::Enter => app.focus_body(),
|
|
||||||
// KeyCode::Right => app.next(),
|
|
||||||
// KeyCode::Left => app.previous(),
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::thread::sleep(Duration::from_millis(20));
|
std::thread::sleep(Duration::from_millis(20));
|
||||||
}
|
}
|
||||||
|
|
85
src/ui.rs
85
src/ui.rs
|
@ -1,79 +1,52 @@
|
||||||
use crate::app::App;
|
use crate::{app::{App, ActiveFrame}, uis::render_history_tab};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
layout::{Constraint, Direction, Layout, Rect},
|
layout::{Constraint, Direction, Layout},
|
||||||
style::{Color, Modifier, Style},
|
widgets::{Block, Borders},
|
||||||
text::{Line, Text},
|
Frame, style::Style,
|
||||||
widgets::{Block, Borders, Tabs, Paragraph},
|
|
||||||
Frame,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::uis::{render_new_transaction_tab, render_history_tab};
|
use crate::uis::{render_navigation_frame, render_new_transaction_tab};
|
||||||
|
|
||||||
|
|
||||||
pub fn render<B: Backend> (f: &mut Frame<B>, app: &App) {
|
pub fn render<B: Backend> (f: &mut Frame<B>, app: &mut App) {
|
||||||
|
|
||||||
let size = f.size();
|
let size = f.size();
|
||||||
let chunks = Layout::default()
|
let chunks = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.constraints([Constraint::Length(3), Constraint::Min(0)].as_ref())
|
.constraints([Constraint::Length(3), Constraint::Min(0), Constraint::Length(3)].as_ref())
|
||||||
.split(size);
|
.split(size);
|
||||||
|
|
||||||
let bottom_block = Block::default()
|
let bottom_block = Block::default()
|
||||||
.borders(Borders::ALL);
|
.borders(Borders::ALL)
|
||||||
|
.border_style({
|
||||||
|
if let ActiveFrame::Navigation = app.states.active_frame {
|
||||||
|
Style::default()
|
||||||
|
} else {
|
||||||
|
Style::default().fg(ratatui::style::Color::Green)
|
||||||
|
}
|
||||||
|
});
|
||||||
f.render_widget(bottom_block, chunks[1]);
|
f.render_widget(bottom_block, chunks[1]);
|
||||||
|
|
||||||
render_statusbar(f, chunks[0], app);
|
render_navigation_frame(f, chunks[0], chunks[2], app);
|
||||||
|
|
||||||
let bottom_chunk = Layout::default()
|
let bottom_chunk = Layout::default()
|
||||||
.direction(Direction::Vertical)
|
.direction(Direction::Vertical)
|
||||||
.margin(1)
|
.margin(1)
|
||||||
.constraints([Constraint::Percentage(100)])
|
.constraints([Constraint::Percentage(100)])
|
||||||
.split(chunks[1]);
|
.split(chunks[1]);
|
||||||
// if app.tabs selected == history,
|
|
||||||
//render_history_tab(f, bottom_chunk[0], app);
|
if let Some(active_frame) = app.states.nav_state.get_active_tab_frametype() {
|
||||||
|
match active_frame {
|
||||||
|
ActiveFrame::History => {
|
||||||
|
render_history_tab(f, bottom_chunk[0], app);
|
||||||
|
}
|
||||||
|
ActiveFrame::NewTransaction => {
|
||||||
render_new_transaction_tab(f, bottom_chunk[0], app);
|
render_new_transaction_tab(f, bottom_chunk[0], app);
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
pub fn render_statusbar<B: Backend> (f: &mut Frame<B>, status_rect: Rect, app: &App) {
|
panic!("ui.rs Render encountered a thought impossible state")
|
||||||
|
}
|
||||||
let status_bar_chunks = Layout::default()
|
}
|
||||||
.direction(Direction::Horizontal)
|
}
|
||||||
.constraints([Constraint::Percentage(75), Constraint::Min(10)])
|
|
||||||
.split(status_rect);
|
|
||||||
|
|
||||||
let left_block = Block::default()
|
|
||||||
.borders(Borders::ALL);
|
|
||||||
let right_block = Block::default()
|
|
||||||
.borders(Borders::ALL);
|
|
||||||
|
|
||||||
|
|
||||||
let titles = app
|
|
||||||
.tabs
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.map(Line::from)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let tabs = Tabs::new(titles)
|
|
||||||
//.block(Block::default().borders(Borders::NONE))
|
|
||||||
.block(left_block)
|
|
||||||
.select(app.tab_index)
|
|
||||||
//.style(Style::default().fg(Color::Cyan))
|
|
||||||
.highlight_style(
|
|
||||||
Style::default()
|
|
||||||
.fg(Color::White)
|
|
||||||
.add_modifier(Modifier::BOLD | Modifier::SLOW_BLINK)
|
|
||||||
.bg(Color::Blue),
|
|
||||||
);
|
|
||||||
|
|
||||||
f.render_widget(tabs, status_bar_chunks[0]);
|
|
||||||
|
|
||||||
let connection_paragraph = Paragraph::new(
|
|
||||||
Text::styled("Aurora",
|
|
||||||
Style::default().fg(Color::Green)
|
|
||||||
)
|
|
||||||
).block(right_block);
|
|
||||||
|
|
||||||
f.render_widget(connection_paragraph, status_bar_chunks[1]);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,56 @@
|
||||||
use ratatui::{backend::Backend, Frame, layout::Rect, widgets::Paragraph, text::Text, style::{Style, Color}};
|
use crossterm::event::{KeyEvent, KeyEventKind, KeyCode};
|
||||||
use crate::app::App;
|
use ratatui::{backend::Backend, Frame, layout::Rect, widgets::{Block, Borders, List, ListItem}, text::Text, style::{Style, Color, Modifier}};
|
||||||
|
use crate::app::{App, StatefulList};
|
||||||
|
|
||||||
|
|
||||||
pub fn render_history_tab<B: Backend> (f: &mut Frame<B>, status_rect: Rect, app: &App) {
|
pub struct HistoryState {
|
||||||
let connection_paragraph = Paragraph::new(
|
pub transacts_list: StatefulList<String>
|
||||||
Text::styled("I'm a ghost!",
|
}
|
||||||
Style::default().fg(Color::Green)
|
|
||||||
)
|
impl HistoryState {
|
||||||
);
|
pub fn new() -> HistoryState {
|
||||||
f.render_widget(connection_paragraph, status_rect);
|
HistoryState {
|
||||||
|
transacts_list: StatefulList::with_items(vec![
|
||||||
|
"Item0".to_string(),
|
||||||
|
"Item1".to_string(),
|
||||||
|
"Item2".to_string(),
|
||||||
|
"Item3".to_string(),
|
||||||
|
"Item4".to_string(),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_event(event: KeyEvent, app: &mut App) {
|
||||||
|
|
||||||
|
if event.kind == KeyEventKind::Press {
|
||||||
|
match event.code {
|
||||||
|
KeyCode::Tab => app.states.transactions.next_tab(),
|
||||||
|
KeyCode::Up => app.states.history.transacts_list.previous(),
|
||||||
|
KeyCode::Down => app.states.history.transacts_list.next(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_history_tab<B: Backend> (f: &mut Frame<B>, body_rect: Rect, app: &mut App) {
|
||||||
|
// Iterate through all elements in the `items` app and append some debug text to it.
|
||||||
|
let items: Vec<ListItem> = app
|
||||||
|
.states.history.transacts_list
|
||||||
|
.items
|
||||||
|
.iter()
|
||||||
|
.map(|i| {
|
||||||
|
ListItem::new(Text::from(i.as_str())).style(Style::default().fg(Color::Black).bg(Color::White))
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let history_items = List::new(items)
|
||||||
|
.block(Block::default().borders(Borders::NONE))
|
||||||
|
.highlight_style(
|
||||||
|
Style::default()
|
||||||
|
.bg(Color::Gray)
|
||||||
|
.add_modifier(Modifier::BOLD)
|
||||||
|
);
|
||||||
|
|
||||||
|
f.render_stateful_widget(history_items, body_rect, &mut app.states.history.transacts_list.state)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,3 +5,6 @@ pub use self::history::render_history_tab;
|
||||||
|
|
||||||
pub mod new_transaction;
|
pub mod new_transaction;
|
||||||
pub use self::new_transaction::render_new_transaction_tab;
|
pub use self::new_transaction::render_new_transaction_tab;
|
||||||
|
|
||||||
|
pub mod navigation_frame;
|
||||||
|
pub use self::navigation_frame::render_navigation_frame;
|
||||||
|
|
120
src/uis/navigation_frame.rs
Normal file
120
src/uis/navigation_frame.rs
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
use crossterm::event::{KeyEvent, KeyEventKind, KeyCode};
|
||||||
|
use ratatui::{widgets::{Borders, Paragraph, Block, Tabs}, backend::Backend, Frame, style::{Style, Color, Modifier}, text::{Text, Line}, layout::{Rect, Layout, Direction, Constraint}};
|
||||||
|
|
||||||
|
use crate::app::{App, ActiveFrame};
|
||||||
|
|
||||||
|
pub struct NavigationState<'a> {
|
||||||
|
pub tabs: Vec<&'a str>,
|
||||||
|
pub tab_index: usize,
|
||||||
|
pub cur_tab_index: usize,
|
||||||
|
|
||||||
|
pub message: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> NavigationState<'a> {
|
||||||
|
pub fn new() -> NavigationState<'a> {
|
||||||
|
NavigationState {
|
||||||
|
tabs: vec!["History", "New Transaction"],
|
||||||
|
tab_index: 0,
|
||||||
|
cur_tab_index: 0,
|
||||||
|
message: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next_tab(&mut self) {
|
||||||
|
self.tab_index = (self.tab_index + 1) % self.tabs.len();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prev_tab(&mut self) {
|
||||||
|
if self.tab_index > 0 {
|
||||||
|
self.tab_index -= 1;
|
||||||
|
} else {
|
||||||
|
self.tab_index = self.tabs.len() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_active_tab_frametype(&self) -> Option<ActiveFrame> {
|
||||||
|
match self.tab_index {
|
||||||
|
0 => Some(ActiveFrame::History),
|
||||||
|
1 => Some(ActiveFrame::NewTransaction),
|
||||||
|
_ => todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_event(event: KeyEvent, app: &mut App) {
|
||||||
|
if event.kind == KeyEventKind::Press {
|
||||||
|
match event.code {
|
||||||
|
KeyCode::Tab => app.states.nav_state.next_tab(),
|
||||||
|
KeyCode::Enter => app.states.active_frame = app.states.nav_state.get_active_tab_frametype().unwrap(),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_navigation_frame<B: Backend> (f: &mut Frame<B>, status_rect: Rect, navbar_rect: Rect, app: &App) {
|
||||||
|
|
||||||
|
let status_bar_chunks = Layout::default()
|
||||||
|
.direction(Direction::Horizontal)
|
||||||
|
.constraints([Constraint::Percentage(75), Constraint::Min(10)])
|
||||||
|
.split(status_rect);
|
||||||
|
|
||||||
|
let left_block = Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style({
|
||||||
|
if let ActiveFrame::Navigation = app.states.active_frame {
|
||||||
|
Style::default().fg(ratatui::style::Color::Green)
|
||||||
|
} else {
|
||||||
|
Style::default()
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let right_block = Block::default()
|
||||||
|
.borders(Borders::ALL);
|
||||||
|
|
||||||
|
|
||||||
|
let titles = app.states.nav_state
|
||||||
|
.tabs
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(Line::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let tabs = Tabs::new(titles)
|
||||||
|
//.block(Block::default().borders(Borders::NONE))
|
||||||
|
.block(left_block)
|
||||||
|
.select(app.states.nav_state.tab_index)
|
||||||
|
//.style(Style::default().fg(Color::Cyan))
|
||||||
|
.highlight_style(
|
||||||
|
Style::default()
|
||||||
|
.fg(Color::White)
|
||||||
|
.add_modifier(Modifier::BOLD | Modifier::SLOW_BLINK)
|
||||||
|
.bg(Color::Blue),
|
||||||
|
);
|
||||||
|
|
||||||
|
f.render_widget(tabs, status_bar_chunks[0]);
|
||||||
|
|
||||||
|
let connection_paragraph = Paragraph::new(
|
||||||
|
Text::styled("Aurora",
|
||||||
|
Style::default().fg(Color::Green)
|
||||||
|
)
|
||||||
|
).block(right_block);
|
||||||
|
|
||||||
|
f.render_widget(connection_paragraph, status_bar_chunks[1]);
|
||||||
|
|
||||||
|
// Navbar section
|
||||||
|
let navbar = {
|
||||||
|
if let None = app.states.nav_state.message {
|
||||||
|
match app.states.active_frame {
|
||||||
|
ActiveFrame::Navigation => "Navigating: `q` to exit".to_string(),
|
||||||
|
_ => "Editing Body: 'q' to go back to navigating".to_string(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
app.states.nav_state.message.clone().unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let bottom_navbar = Paragraph::new(
|
||||||
|
Text::styled(navbar, Style::default().fg(Color::White))
|
||||||
|
)
|
||||||
|
.block(Block::default().borders(Borders::ALL));
|
||||||
|
f.render_widget(bottom_navbar, navbar_rect);
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crossterm::event::{Event, KeyEvent, KeyEventKind, KeyCode};
|
use crossterm::event::{KeyEvent, KeyEventKind, KeyCode};
|
||||||
use ratatui::{backend::Backend, Frame, layout::{Rect, Layout, Direction, Constraint}, widgets::{Paragraph, Borders, Block}, text::Text, style::{Style, Color}};
|
use ratatui::{backend::Backend, Frame, layout::{Rect, Layout, Direction, Constraint}, widgets::{Paragraph, Borders, Block}, text::Text, style::{Style, Color}};
|
||||||
|
|
||||||
pub struct NewTransactionTabState<'a> {
|
pub struct NewTransactionTabState<'a> {
|
||||||
|
@ -10,7 +10,7 @@ pub struct NewTransactionTabState<'a> {
|
||||||
impl<'a> NewTransactionTabState<'a> {
|
impl<'a> NewTransactionTabState<'a> {
|
||||||
pub fn new() -> NewTransactionTabState<'a> {
|
pub fn new() -> NewTransactionTabState<'a> {
|
||||||
NewTransactionTabState {
|
NewTransactionTabState {
|
||||||
cur_tab_index: 1,
|
cur_tab_index: 0,
|
||||||
tabs: vec!["Quick Entry", "Manual Entry"]
|
tabs: vec!["Quick Entry", "Manual Entry"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,14 +22,10 @@ impl<'a> NewTransactionTabState<'a> {
|
||||||
pub fn handle_event(event: KeyEvent, app: &mut App) {
|
pub fn handle_event(event: KeyEvent, app: &mut App) {
|
||||||
if event.kind == KeyEventKind::Press {
|
if event.kind == KeyEventKind::Press {
|
||||||
match event.code {
|
match event.code {
|
||||||
KeyCode::Char('q') => app.focus_navigation(),
|
KeyCode::Tab => app.states.transactions.next_tab(),
|
||||||
KeyCode::Tab => app.new_transaction_tab_state.next_tab(),
|
|
||||||
// KeyCode::Right => app.next(),
|
|
||||||
// KeyCode::Left => app.previous(),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,8 +38,8 @@ pub fn render_new_transaction_tab<B: Backend> (f: &mut Frame<B>, body_rect: Rect
|
||||||
|
|
||||||
// Render the custom tab bar
|
// Render the custom tab bar
|
||||||
let mut constraints: Vec<Constraint> = vec![];
|
let mut constraints: Vec<Constraint> = vec![];
|
||||||
let tab_percent: u16 = (100 / app.new_transaction_tab_state.tabs.len()) as u16;
|
let tab_percent: u16 = (100 / app.states.transactions.tabs.len()) as u16;
|
||||||
for _ in 0..app.new_transaction_tab_state.tabs.len() {
|
for _ in 0..app.states.transactions.tabs.len() {
|
||||||
constraints.push(Constraint::Percentage(tab_percent));
|
constraints.push(Constraint::Percentage(tab_percent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,10 +48,10 @@ pub fn render_new_transaction_tab<B: Backend> (f: &mut Frame<B>, body_rect: Rect
|
||||||
.constraints(constraints)
|
.constraints(constraints)
|
||||||
.split(chunks[0]);
|
.split(chunks[0]);
|
||||||
|
|
||||||
for i in 0..app.new_transaction_tab_state.tabs.len() {
|
for i in 0..app.states.transactions.tabs.len() {
|
||||||
|
|
||||||
let tab = Paragraph::new(
|
let tab = Paragraph::new(
|
||||||
Text::styled(app.new_transaction_tab_state.tabs[i],
|
Text::styled(app.states.transactions.tabs[i],
|
||||||
Style::default().fg(Color::White)
|
Style::default().fg(Color::White)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -64,7 +60,7 @@ pub fn render_new_transaction_tab<B: Backend> (f: &mut Frame<B>, body_rect: Rect
|
||||||
Block::default()
|
Block::default()
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.style({
|
.style({
|
||||||
if app.new_transaction_tab_state.cur_tab_index == i {
|
if app.states.transactions.cur_tab_index == i {
|
||||||
Style::default().bg(Color::Blue)
|
Style::default().bg(Color::Blue)
|
||||||
} else {
|
} else {
|
||||||
Style::default()
|
Style::default()
|
||||||
|
|
Loading…
Reference in a new issue