feat: Added basic two level navigation
This commit is contained in:
parent
e4a840d7e4
commit
6ef492ee10
5 changed files with 134 additions and 12 deletions
27
src/app.rs
27
src/app.rs
|
@ -1,10 +1,21 @@
|
|||
|
||||
use crate::uis::new_transaction::NewTransactionTabState;
|
||||
|
||||
pub type AppResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
||||
|
||||
pub enum FocusedBlock {
|
||||
Navigation,
|
||||
Body,
|
||||
}
|
||||
|
||||
pub struct App<'a> {
|
||||
pub running: bool,
|
||||
pub tabs: Vec<&'a str>,
|
||||
pub tab_index: usize,
|
||||
pub focus: FocusedBlock,
|
||||
|
||||
pub new_transaction_tab_state: NewTransactionTabState<'a>,
|
||||
|
||||
}
|
||||
|
||||
impl<'a> App<'a> {
|
||||
|
@ -12,8 +23,11 @@ impl<'a> App<'a> {
|
|||
App {
|
||||
running: true,
|
||||
|
||||
tabs: vec!["Tab1", "Tab2", "Tab3"],
|
||||
tabs: vec!["History", "Tab2", "Tab3"],
|
||||
tab_index: 0,
|
||||
focus: FocusedBlock::Navigation,
|
||||
|
||||
new_transaction_tab_state: NewTransactionTabState::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,4 +41,13 @@ impl<'a> App<'a> {
|
|||
} else {
|
||||
self.tab_index = self.tabs.len() - 1;
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
||||
pub fn focus_navigation(&mut self) {
|
||||
self.focus = FocusedBlock::Navigation;
|
||||
}
|
||||
|
||||
pub fn focus_body(&mut self) {
|
||||
self.focus = FocusedBlock::Body;
|
||||
}
|
||||
}
|
||||
|
|
35
src/main.rs
35
src/main.rs
|
@ -7,8 +7,9 @@ use ratatui::{
|
|||
Terminal,
|
||||
};
|
||||
|
||||
use recount::app::{App, AppResult};
|
||||
use recount::app::{App, AppResult, FocusedBlock};
|
||||
use recount::tui::Tui;
|
||||
use recount::uis::new_transaction::NewTransactionTabState;
|
||||
|
||||
fn main() -> AppResult<()> {
|
||||
// Create an application.
|
||||
|
@ -28,16 +29,34 @@ fn main() -> AppResult<()> {
|
|||
|
||||
// Handle events.
|
||||
if let Event::Key(key) = event::read()? {
|
||||
if key.kind == KeyEventKind::Press {
|
||||
match key.code {
|
||||
KeyCode::Char('q') => break,
|
||||
KeyCode::Tab => app.next_tab(),
|
||||
// KeyCode::Right => app.next(),
|
||||
// KeyCode::Left => app.previous(),
|
||||
_ => {}
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use ratatui::{
|
|||
Frame,
|
||||
};
|
||||
|
||||
use crate::uis::render_history_tab;
|
||||
use crate::uis::{render_new_transaction_tab, render_history_tab};
|
||||
|
||||
|
||||
pub fn render<B: Backend> (f: &mut Frame<B>, app: &App) {
|
||||
|
@ -31,7 +31,8 @@ pub fn render<B: Backend> (f: &mut Frame<B>, app: &App) {
|
|||
.constraints([Constraint::Percentage(100)])
|
||||
.split(chunks[1]);
|
||||
// if app.tabs selected == history,
|
||||
render_history_tab(f, bottom_chunk[0], app);
|
||||
//render_history_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) {
|
||||
|
|
|
@ -2,3 +2,6 @@
|
|||
|
||||
pub mod history;
|
||||
pub use self::history::render_history_tab;
|
||||
|
||||
pub mod new_transaction;
|
||||
pub use self::new_transaction::render_new_transaction_tab;
|
||||
|
|
76
src/uis/new_transaction.rs
Normal file
76
src/uis/new_transaction.rs
Normal file
|
@ -0,0 +1,76 @@
|
|||
use crate::app::App;
|
||||
use crossterm::event::{Event, KeyEvent, KeyEventKind, KeyCode};
|
||||
use ratatui::{backend::Backend, Frame, layout::{Rect, Layout, Direction, Constraint}, widgets::{Paragraph, Borders, Block}, text::Text, style::{Style, Color}};
|
||||
|
||||
pub struct NewTransactionTabState<'a> {
|
||||
pub cur_tab_index: usize,
|
||||
pub tabs: Vec<&'a str>,
|
||||
}
|
||||
|
||||
impl<'a> NewTransactionTabState<'a> {
|
||||
pub fn new() -> NewTransactionTabState<'a> {
|
||||
NewTransactionTabState {
|
||||
cur_tab_index: 1,
|
||||
tabs: vec!["Quick Entry", "Manual Entry"]
|
||||
}
|
||||
}
|
||||
|
||||
pub fn next_tab(&mut self) {
|
||||
self.cur_tab_index = (self.cur_tab_index + 1) % self.tabs.len();
|
||||
}
|
||||
|
||||
pub fn handle_event(event: KeyEvent, app: &mut App) {
|
||||
if event.kind == KeyEventKind::Press {
|
||||
match event.code {
|
||||
KeyCode::Char('q') => app.focus_navigation(),
|
||||
KeyCode::Tab => app.new_transaction_tab_state.next_tab(),
|
||||
// KeyCode::Right => app.next(),
|
||||
// KeyCode::Left => app.previous(),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_new_transaction_tab<B: Backend> (f: &mut Frame<B>, body_rect: Rect, app: &App) {
|
||||
|
||||
let chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([Constraint::Length(3), Constraint::Min(0)])
|
||||
.split(body_rect);
|
||||
|
||||
// Render the custom tab bar
|
||||
let mut constraints: Vec<Constraint> = vec![];
|
||||
let tab_percent: u16 = (100 / app.new_transaction_tab_state.tabs.len()) as u16;
|
||||
for _ in 0..app.new_transaction_tab_state.tabs.len() {
|
||||
constraints.push(Constraint::Percentage(tab_percent));
|
||||
}
|
||||
|
||||
let tab_chunks = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints(constraints)
|
||||
.split(chunks[0]);
|
||||
|
||||
for i in 0..app.new_transaction_tab_state.tabs.len() {
|
||||
|
||||
let tab = Paragraph::new(
|
||||
Text::styled(app.new_transaction_tab_state.tabs[i],
|
||||
Style::default().fg(Color::White)
|
||||
)
|
||||
)
|
||||
.alignment(ratatui::layout::Alignment::Center)
|
||||
.block(
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.style({
|
||||
if app.new_transaction_tab_state.cur_tab_index == i {
|
||||
Style::default().bg(Color::Blue)
|
||||
} else {
|
||||
Style::default()
|
||||
}
|
||||
})
|
||||
);
|
||||
f.render_widget(tab, tab_chunks[i])
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue