travail sur add transaction

This commit is contained in:
thatscringebro
2026-03-11 16:05:56 -04:00
parent e58387a1bf
commit 461468ff1b
6 changed files with 192 additions and 7 deletions

View File

@@ -1,3 +1,4 @@
use chrono::{DateTime, Local, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};
use sqlite::Connection;
use crate::{data_layer, entities::*, enums::*};
@@ -9,6 +10,8 @@ pub struct App {
pub trx_table: TrxTable,
pub new_account: Account,
pub new_transaction: Transaction,
pub selected_transaction_input: TransactionInput,
pub current_input: String,
pub connection: Connection,
}
@@ -31,6 +34,8 @@ impl App {
trx_table: TrxTable::new(),
new_account: Account::new(0, String::new(), AccountType::Cash),
new_transaction: Transaction::new_empty(),
selected_transaction_input: TransactionInput::Type,
current_input: String::new(),
connection: con,
};
}
@@ -71,4 +76,89 @@ impl App {
self.trx_table.add_tr(tr);
self.new_transaction = Transaction::new_empty();
}
pub fn next_tr_input(&mut self) {
match self.selected_transaction_input {
TransactionInput::Type => {
self.selected_transaction_input = TransactionInput::Amount;
self.new_transaction.set_type(
self.current_input
.parse::<i64>()
.expect("Failed to parse data"),
&self.connection,
);
}
TransactionInput::Amount => {
self.selected_transaction_input = TransactionInput::Date;
self.new_transaction.set_amount(
self.current_input
.parse::<f64>()
.expect("Failed to parse data"),
);
}
TransactionInput::Date => {
self.selected_transaction_input = TransactionInput::Description;
let date = NaiveDate::parse_from_str(&self.current_input, "%Y-%m-%d")
.expect("Faile to parse data");
let time = NaiveTime::from_hms_opt(5, 0, 0).unwrap(); // to account for my local datetime
self.new_transaction
.set_date(Local.from_utc_datetime(&NaiveDateTime::new(date, time)));
}
TransactionInput::Description => {
self.new_transaction.set_desc(self.current_input.clone())
}
}
self.set_current_input();
}
pub fn previous_tr_input(&mut self) {
match self.selected_transaction_input {
TransactionInput::Type => {
self.new_transaction.set_type(
self.current_input
.parse::<i64>()
.expect("Failed to parse data"),
&self.connection,
);
}
TransactionInput::Amount => {
self.selected_transaction_input = TransactionInput::Type;
self.new_transaction.set_amount(
self.current_input
.parse::<f64>()
.expect("Failed to parse data"),
);
}
TransactionInput::Date => {
self.selected_transaction_input = TransactionInput::Amount;
let date = NaiveDate::parse_from_str(&self.current_input, "%Y-%m-%d")
.expect("Faile to parse data");
let time = NaiveTime::from_hms_opt(5, 0, 0).unwrap(); // to account for my local datetime
self.new_transaction
.set_date(Local.from_utc_datetime(&NaiveDateTime::new(date, time)));
}
TransactionInput::Description => {
self.selected_transaction_input = TransactionInput::Date;
self.new_transaction.set_desc(self.current_input.clone());
}
}
self.set_current_input();
}
fn set_current_input(&mut self) {
match self.selected_transaction_input {
TransactionInput::Type => {
self.current_input = self.new_transaction.get_type().get_id().to_string()
}
TransactionInput::Amount => {
self.current_input = self.new_transaction.get_amount().to_string()
}
TransactionInput::Date => {
self.current_input = self
.new_transaction
.get_date()
.format("%Y-%m-%d")
.to_string()
}
TransactionInput::Description => self.current_input = self.new_transaction.get_desc(),
}
}
}

View File

@@ -187,7 +187,7 @@ pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction {
}
let mut statement = con.prepare(query).unwrap();
statement.bind((1, tr.get_account().get_id())).unwrap();
statement.bind((1, tr.get_account_id())).unwrap();
statement.bind((2, tr.get_type().get_id())).unwrap();
statement.bind((3, tr.get_amount())).unwrap();
statement.bind((4, tr.get_date().timestamp())).unwrap();
@@ -206,7 +206,7 @@ pub fn upsert_transaction(con: &Connection, tr: Transaction) -> Transaction {
return Transaction::new(
id,
tr.get_account().get_id(),
tr.get_account_id(),
tr.get_amount(),
tr.get_date_utc(),
tr.get_desc(),

View File

@@ -11,7 +11,6 @@ pub struct Transaction {
description: String,
type_id: i64,
account: Account,
tr_type: TransactionType,
}
@@ -32,7 +31,6 @@ impl Transaction {
date: date,
description: desc,
type_id: type_id,
account: data_layer::get_account(con, ac_id),
tr_type: data_layer::get_transaction_type(con, type_id),
}
}
@@ -45,7 +43,6 @@ impl Transaction {
date: DateTime::from_timestamp(0, 0).unwrap(),
description: "".to_string(),
type_id: 0,
account: Account::new(0, "".to_string(), super::AccountType::Cash),
tr_type: TransactionType::new(0, "".to_string()),
}
}
@@ -57,6 +54,9 @@ impl Transaction {
pub fn get_amount(&self) -> f64 {
return self.amount;
}
pub fn set_amount(&mut self, amnt: f64) {
self.amount = amnt;
}
pub fn get_date(&self) -> DateTime<Local> {
return Local.from_utc_datetime(&self.date.naive_local());
@@ -64,18 +64,31 @@ impl Transaction {
pub fn get_date_utc(&self) -> DateTime<Utc> {
return self.date;
}
pub fn set_date(&mut self, date: DateTime<Local>) {
self.date = date.to_utc();
}
pub fn get_desc(&self) -> String {
return self.description.clone();
}
pub fn set_desc(&mut self, desc: String) {
self.description = desc;
}
pub fn get_account(&self) -> Account {
return self.account.clone();
pub fn get_account_id(&self) -> i64 {
return self.account_id;
}
pub fn set_account_id(&mut self, ac_id: i64) {
self.account_id = ac_id;
}
pub fn get_type(&self) -> TransactionType {
return self.tr_type.clone();
}
pub fn set_type(&mut self, tr_id: i64, con: &Connection) {
self.type_id = tr_id;
self.tr_type = data_layer::get_transaction_type(con, tr_id);
}
}
#[derive(Clone)]

View File

@@ -8,3 +8,11 @@ pub enum CurrentScreen {
NewAccount,
NewTransaction,
}
#[derive(PartialEq)]
pub enum TransactionInput {
Type,
Amount,
Date,
Description,
}

View File

@@ -4,6 +4,7 @@ mod entities;
mod enums;
mod ui;
use crate::{app::App, enums::*, ui::ui};
use chrono::Local;
use entities::{Account, AccountType, Transaction};
use ratatui::{
Terminal,
@@ -87,6 +88,9 @@ where
}
CurrentWidget::TrxList => {
app.current_screen = CurrentScreen::NewTransaction;
app.new_transaction
.set_account_id(app.acc_list.get_selected_id());
app.new_transaction.set_date(Local::now());
}
_ => {}
},
@@ -104,10 +108,22 @@ where
_ => {}
},
CurrentScreen::NewTransaction => match key.code {
KeyCode::Down => {
app.next_tr_input();
}
KeyCode::Up => {
app.previous_tr_input();
}
KeyCode::Enter => {
app.save_new_tr();
app.current_screen = CurrentScreen::Main;
}
KeyCode::Backspace => {
app.current_input.pop();
}
KeyCode::Char(value) => {
app.current_input.push(value);
}
KeyCode::Esc => {
app.current_screen = CurrentScreen::Main;
app.new_transaction = Transaction::new_empty();

View File

@@ -3,6 +3,7 @@ use crate::{
entities::{Account, Transaction},
enums::*,
};
use chrono::{Date, Local};
use ratatui::{
Frame,
layout::{Constraint, Direction, Layout, Rect},
@@ -120,6 +121,41 @@ pub fn ui(frame: &mut Frame, app: &mut App) {
let area = centered_rect(50, 40, frame.area());
frame.render_widget(popup, area);
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(1)
.constraints([
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
Constraint::Length(3),
])
.split(area);
let tr_type = Paragraph::new(tr_input_str(TransactionInput::Type, app))
.style(tr_input_style(TransactionInput::Type, app))
.block(Block::default().borders(Borders::BOTTOM).title("Type"));
frame.render_widget(tr_type, chunks[0]);
let amnt = Paragraph::new(tr_input_str(TransactionInput::Amount, app))
.style(tr_input_style(TransactionInput::Amount, app))
.block(Block::default().borders(Borders::BOTTOM).title("Amount"));
frame.render_widget(amnt, chunks[1]);
let date = Paragraph::new(tr_input_str(TransactionInput::Date, app))
.style(tr_input_style(TransactionInput::Date, app))
.block(Block::default().borders(Borders::BOTTOM).title("Date"));
frame.render_widget(date, chunks[2]);
let desc = Paragraph::new(tr_input_str(TransactionInput::Description, app))
.style(tr_input_style(TransactionInput::Description, app))
.block(
Block::default()
.borders(Borders::BOTTOM)
.title("Description"),
);
frame.render_widget(desc, chunks[3]);
}
if let CurrentScreen::Exiting = app.current_screen {
@@ -162,6 +198,28 @@ fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
.split(popup_layout[1])[1];
}
fn tr_input_style(input: TransactionInput, app: &mut App) -> Style {
if app.selected_transaction_input == input {
return SELECTED_STYLE;
}
return Style::default();
}
fn tr_input_str(input: TransactionInput, app: &mut App) -> String {
if app.selected_transaction_input == input {
return app.current_input.clone();
}
match input {
TransactionInput::Type => app.new_transaction.get_type().get_id().to_string(),
TransactionInput::Amount => app.new_transaction.get_amount().to_string(),
TransactionInput::Date => app
.new_transaction
.get_date()
.format("%Y-%m-%d")
.to_string(),
TransactionInput::Description => app.new_transaction.get_desc(),
}
}
impl From<&Account> for ListItem<'_> {
fn from(value: &Account) -> Self {
let line = Line::styled(