début du ui
This commit is contained in:
parent
55dfd16cd2
commit
33fb39e732
42
src/app.rs
42
src/app.rs
@ -1,19 +1,49 @@
|
|||||||
|
use ratatui::widgets::ListState;
|
||||||
use sqlite::Connection;
|
use sqlite::Connection;
|
||||||
|
|
||||||
|
use crate::{data_layer, entities::Account};
|
||||||
|
|
||||||
pub enum CurrentScreen {
|
pub enum CurrentScreen {
|
||||||
Main,
|
Main,
|
||||||
Exiting,
|
Exiting,
|
||||||
}
|
}
|
||||||
|
pub enum CurrentWidget {
|
||||||
|
AccountList,
|
||||||
|
TrxInfo,
|
||||||
|
TrxList,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AccountList {
|
||||||
|
accounts: Vec<Account>,
|
||||||
|
pub state: ListState,
|
||||||
|
}
|
||||||
|
impl AccountList {
|
||||||
|
fn new() -> AccountList {
|
||||||
|
return AccountList {
|
||||||
|
accounts: Vec::new(),
|
||||||
|
state: ListState::default(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_accounts(&self, con: &Connection) -> Vec<Account> {
|
||||||
|
if self.accounts.iter().count() == 0 {
|
||||||
|
return data_layer::get_accounts(con);
|
||||||
|
}
|
||||||
|
return self.accounts.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
pub current_screen: CurrentScreen,
|
pub current_screen: CurrentScreen,
|
||||||
connection: Connection,
|
pub current_widget: CurrentWidget,
|
||||||
|
pub acc_list: AccountList,
|
||||||
|
pub connection: Connection,
|
||||||
exit: bool,
|
exit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new() -> App {
|
pub fn new() -> App {
|
||||||
let connection = match Connection::open("ft_rs.db") {
|
let con = match Connection::open("ft_rs.db") {
|
||||||
Ok(con) => con,
|
Ok(con) => con,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error opening database: {}", e);
|
eprintln!("Error opening database: {}", e);
|
||||||
@ -22,8 +52,14 @@ impl App {
|
|||||||
};
|
};
|
||||||
return App {
|
return App {
|
||||||
current_screen: CurrentScreen::Main,
|
current_screen: CurrentScreen::Main,
|
||||||
connection: connection,
|
current_widget: CurrentWidget::AccountList,
|
||||||
|
acc_list: AccountList::new(),
|
||||||
|
connection: con,
|
||||||
exit: false,
|
exit: false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_list_accounts(&self) -> Vec<Account> {
|
||||||
|
return self.acc_list.get_accounts(&self.connection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use crate::{
|
|||||||
app::{App, CurrentScreen},
|
app::{App, CurrentScreen},
|
||||||
ui::ui,
|
ui::ui,
|
||||||
};
|
};
|
||||||
|
use app::CurrentWidget;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
Terminal,
|
Terminal,
|
||||||
crossterm::{
|
crossterm::{
|
||||||
@ -55,6 +56,12 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> io::Result<
|
|||||||
KeyCode::Char('q') => {
|
KeyCode::Char('q') => {
|
||||||
app.current_screen = CurrentScreen::Exiting;
|
app.current_screen = CurrentScreen::Exiting;
|
||||||
}
|
}
|
||||||
|
KeyCode::Right => {
|
||||||
|
app.current_widget = CurrentWidget::TrxList;
|
||||||
|
}
|
||||||
|
KeyCode::Left => {
|
||||||
|
app.current_widget = CurrentWidget::AccountList;
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
},
|
},
|
||||||
CurrentScreen::Exiting => match key.code {
|
CurrentScreen::Exiting => match key.code {
|
||||||
@ -100,7 +107,7 @@ fn run_app<B: Backend>(terminal: &mut Terminal<B>, app: &mut App) -> io::Result<
|
|||||||
|
|
||||||
// match choice {
|
// match choice {
|
||||||
// "1" => {
|
// "1" => {
|
||||||
// let accounts = data_layer::get_accounts(&connection);
|
// let accounts = data_layer::get_accounts)(&connection);
|
||||||
// let mut total = 0.0;
|
// let mut total = 0.0;
|
||||||
// for ac in accounts.iter() {
|
// for ac in accounts.iter() {
|
||||||
// let ac_total = ac.get_total(&connection);
|
// let ac_total = ac.get_total(&connection);
|
||||||
|
|||||||
98
src/ui.rs
98
src/ui.rs
@ -1,16 +1,84 @@
|
|||||||
use crate::app::{App, CurrentScreen};
|
use crate::{
|
||||||
|
app::{App, CurrentScreen, CurrentWidget},
|
||||||
|
entities::Account,
|
||||||
|
};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
Frame,
|
Frame,
|
||||||
layout::{Constraint, Direction, Layout, Rect},
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
style::{Color, Style},
|
style::{
|
||||||
text::Text,
|
Color, Modifier, Style, Stylize,
|
||||||
widgets::{Block, Borders, Clear, Paragraph, Wrap},
|
palette::tailwind::{BLUE, GREEN, SLATE},
|
||||||
|
},
|
||||||
|
text::{Line, Text},
|
||||||
|
widgets::{Block, Borders, Clear, HighlightSpacing, List, ListItem, Paragraph, Widget, Wrap},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn ui(frame: &mut Frame, app: &App) {
|
const NORMAL_ROW_BG: Color = SLATE.c950;
|
||||||
if let CurrentScreen::Exiting = app.current_screen {
|
const ALT_ROW_BG_COLOR: Color = SLATE.c900;
|
||||||
frame.render_widget(Clear, frame.area());
|
const TEXT_FG_COLOR: Color = SLATE.c200;
|
||||||
|
const SELECTED_STYLE: Style = Style::new().bg(SLATE.c800).add_modifier(Modifier::BOLD);
|
||||||
|
|
||||||
|
pub fn ui(frame: &mut Frame, app: &App) {
|
||||||
|
let layout = Layout::default()
|
||||||
|
.direction(Direction::Horizontal)
|
||||||
|
.constraints(vec![Constraint::Percentage(20), Constraint::Percentage(80)])
|
||||||
|
.split(frame.area());
|
||||||
|
let right_layout = Layout::default()
|
||||||
|
.direction(Direction::Vertical)
|
||||||
|
.constraints(vec![Constraint::Percentage(10), Constraint::Percentage(90)])
|
||||||
|
.split(layout[1]);
|
||||||
|
|
||||||
|
let mut ac_block = Block::default()
|
||||||
|
.title("Accounts")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(Style::new().fg(Color::DarkGray));
|
||||||
|
let mut info_block = Block::default()
|
||||||
|
.title("Account info")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(Style::new().fg(Color::DarkGray));
|
||||||
|
let mut trx_block = Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_style(Style::new().fg(Color::DarkGray));
|
||||||
|
|
||||||
|
let active_style = Style::default();
|
||||||
|
match app.current_widget {
|
||||||
|
CurrentWidget::AccountList => ac_block = ac_block.border_style(active_style),
|
||||||
|
CurrentWidget::TrxInfo => info_block = info_block.border_style(active_style),
|
||||||
|
CurrentWidget::TrxList => trx_block = trx_block.border_style(active_style),
|
||||||
|
};
|
||||||
|
|
||||||
|
let items: Vec<ListItem> = app
|
||||||
|
.get_list_accounts()
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, acc)| {
|
||||||
|
let color = alternate_colors(i);
|
||||||
|
ListItem::from(acc).bg(color)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let list = List::new(items)
|
||||||
|
.block(ac_block)
|
||||||
|
.highlight_style(SELECTED_STYLE)
|
||||||
|
.highlight_symbol(">")
|
||||||
|
.highlight_spacing(HighlightSpacing::Always);
|
||||||
|
|
||||||
|
frame.render_widget(list, layout[0]);
|
||||||
|
|
||||||
|
let info = if let Some(i) = app.acc_list.state.selected() {
|
||||||
|
format!(
|
||||||
|
"Total: {}",
|
||||||
|
app.get_list_accounts()[i]
|
||||||
|
.get_total(&app.connection)
|
||||||
|
.to_string()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
"No account selected...".to_string()
|
||||||
|
};
|
||||||
|
frame.render_widget(Paragraph::new(info).block(info_block), right_layout[0]);
|
||||||
|
frame.render_widget(Paragraph::new("inner 1").block(trx_block), right_layout[1]);
|
||||||
|
|
||||||
|
if let CurrentScreen::Exiting = app.current_screen {
|
||||||
let popup = Block::default()
|
let popup = Block::default()
|
||||||
.title("Exiting program")
|
.title("Exiting program")
|
||||||
.borders(Borders::all())
|
.borders(Borders::all())
|
||||||
@ -25,7 +93,7 @@ pub fn ui(frame: &mut Frame, app: &App) {
|
|||||||
.block(popup)
|
.block(popup)
|
||||||
.wrap(Wrap { trim: false });
|
.wrap(Wrap { trim: false });
|
||||||
|
|
||||||
let area = centered_rect(60, 20, frame.area());
|
let area = centered_rect(50, 20, frame.area());
|
||||||
frame.render_widget(exit_paragraph, area);
|
frame.render_widget(exit_paragraph, area);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -49,3 +117,17 @@ fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
|
|||||||
])
|
])
|
||||||
.split(popup_layout[1])[1];
|
.split(popup_layout[1])[1];
|
||||||
}
|
}
|
||||||
|
const fn alternate_colors(i: usize) -> Color {
|
||||||
|
if i % 2 == 0 {
|
||||||
|
NORMAL_ROW_BG
|
||||||
|
} else {
|
||||||
|
ALT_ROW_BG_COLOR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&Account> for ListItem<'_> {
|
||||||
|
fn from(value: &Account) -> Self {
|
||||||
|
let line = Line::styled(value.get_name(), TEXT_FG_COLOR);
|
||||||
|
ListItem::new(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user