pub mod budget;
pub mod category_manager;
pub mod category_summary;
pub mod dialog;
pub mod filter;
pub mod fuzzy_search;
pub mod help;
pub mod help_popup;
pub mod helpers;
pub mod recurring;
pub mod settings;
pub mod status;
pub mod summary;
pub mod transaction_form;
pub mod transaction_io;
pub mod transaction_table;
pub mod update_popup;
use crate::app::state::{App, AppMode};
use ratatui::Frame;
pub(crate) fn ui(f: &mut Frame, app: &mut App) {
let render_mode =
if app.mode == AppMode::KeybindingsInfo || app.mode == AppMode::KeybindingDetail {
app.previous_mode.unwrap_or(AppMode::Normal)
} else {
app.mode
};
let filter_bar_height = if matches!(
render_mode,
AppMode::Filtering | AppMode::CategoryCatalogFilter
) {
3
} else {
0
};
let status_bar_height = if app.status_message.is_some() { 3 } else { 0 };
let summary_bar_height = if matches!(
render_mode,
AppMode::CategorySummary
| AppMode::Budget
| AppMode::Settings
| AppMode::CategoryCatalog
| AppMode::CategoryCatalogFilter
| AppMode::CategoryEditor
| AppMode::ConfirmCategoryDelete
| AppMode::Adding
| AppMode::Editing
| AppMode::FuzzyFinding
| AppMode::RecurringSettings
| AppMode::SelectingRecurrenceFrequency
| AppMode::SelectingCategory
| AppMode::SelectingSubcategory
| AppMode::KeybindingsInfo
| AppMode::KeybindingDetail
| AppMode::ImportTransactions
| AppMode::ExportTransactions
) {
0
} else {
3
};
let help_bar_height = if app.hide_help_bar { 0 } else { 3 };
let main_chunks = ratatui::layout::Layout::default()
.direction(ratatui::layout::Direction::Vertical)
.constraints([
ratatui::layout::Constraint::Min(0),
ratatui::layout::Constraint::Length(filter_bar_height),
ratatui::layout::Constraint::Length(summary_bar_height),
ratatui::layout::Constraint::Length(status_bar_height),
ratatui::layout::Constraint::Length(help_bar_height),
])
.split(f.area());
let main_area = main_chunks[0];
let filter_area = main_chunks[1];
let summary_area = main_chunks[2];
let status_area = main_chunks[3];
let help_area = main_chunks[4];
match render_mode {
AppMode::Normal | AppMode::Filtering => {
transaction_table::render_transaction_table(f, app, main_area);
}
AppMode::AdvancedFiltering => {
filter::render_advanced_filter_form(f, app, main_area);
}
AppMode::SelectingFilterCategory | AppMode::SelectingFilterSubcategory => {
filter::render_advanced_filter_form(f, app, main_area);
dialog::render_selection_popup(f, app, main_area);
}
AppMode::Adding | AppMode::Editing => {
transaction_form::render_transaction_form(f, app, main_area);
}
AppMode::ConfirmDelete => {
transaction_table::render_transaction_table(f, app, main_area);
dialog::render_confirmation_dialog(f, "Confirm Delete? (y/n)", main_area);
}
AppMode::Summary => {
summary::render_summary_view(f, app, main_area);
}
AppMode::SelectingCategory | AppMode::SelectingSubcategory => {
transaction_form::render_transaction_form(f, app, main_area);
dialog::render_selection_popup(f, app, main_area);
}
AppMode::FuzzyFinding => {
transaction_form::render_transaction_form(f, app, main_area);
fuzzy_search::render_fuzzy_search(f, app, main_area);
}
AppMode::CategorySummary => {
category_summary::render_category_summary_view(f, app, main_area);
}
AppMode::Budget => {
budget::render_budget_view(f, app, main_area);
}
AppMode::CategoryCatalog | AppMode::CategoryCatalogFilter => {
category_manager::render_category_catalog(f, app, main_area);
}
AppMode::CategoryEditor => {
category_manager::render_category_editor(f, app, main_area);
}
AppMode::ConfirmCategoryDelete => {
category_manager::render_category_catalog(f, app, main_area);
dialog::render_confirmation_dialog(f, "Delete selected category? (y/n)", main_area);
}
AppMode::Settings => {
transaction_table::render_transaction_table(f, app, main_area);
settings::render_settings_form(f, app, main_area);
}
AppMode::ImportTransactions | AppMode::ExportTransactions => {
transaction_table::render_transaction_table(f, app, main_area);
settings::render_settings_form(f, app, main_area);
transaction_io::render_io_prompt(f, app, main_area);
}
AppMode::RecurringSettings => {
recurring::render_recurring_settings(f, app, main_area);
}
AppMode::SelectingRecurrenceFrequency => {
recurring::render_recurring_settings(f, app, main_area);
dialog::render_selection_popup(f, app, main_area);
}
_ => {}
}
if render_mode == AppMode::Filtering {
filter::render_filter_input(f, app, filter_area);
}
if render_mode == AppMode::CategoryCatalogFilter {
category_manager::render_category_filter_input(f, app, filter_area);
}
let year_filter = match render_mode {
AppMode::Summary => app
.summary_years
.get(app.selected_summary_year_index)
.copied(),
AppMode::CategorySummary => app
.category_summary_years
.get(app.category_summary_year_index)
.copied(),
AppMode::Budget => app.selected_budget_year(),
_ => None, };
if let Some(msg) = &app.status_message {
status::render_status_bar(f, msg, status_area);
}
summary::render_summary_bar(f, app, summary_area, year_filter);
if !app.hide_help_bar {
help::render_help_bar(f, app, help_area);
}
if app.mode == AppMode::KeybindingsInfo || app.mode == AppMode::KeybindingDetail {
help_popup::render_keybindings_popup(f, app, f.area());
}
if app.show_update_popup {
update_popup::render_update_popup(f, app, f.area());
}
if render_mode == AppMode::Filtering {
let cursor_x = app.simple_filter_content[..app.simple_filter_cursor]
.chars()
.count() as u16;
f.set_cursor_position(ratatui::layout::Position::new(
filter_area.x + cursor_x + 1,
filter_area.y + 1,
));
}
if render_mode == AppMode::CategoryCatalogFilter {
let cursor_x = app.category_filter_query[..app.category_filter_cursor]
.chars()
.count() as u16;
f.set_cursor_position(ratatui::layout::Position::new(
filter_area.x + cursor_x + 1,
filter_area.y + 1,
));
}
if app.mode == AppMode::FuzzyFinding {
let popup_area = helpers::centered_rect(60, 60, main_area);
let chunks = ratatui::layout::Layout::default()
.direction(ratatui::layout::Direction::Vertical)
.constraints([
ratatui::layout::Constraint::Length(3),
ratatui::layout::Constraint::Min(0),
])
.split(popup_area);
let search_area = chunks[0];
let cursor_x = app.search_query.chars().count() as u16;
let max_width = search_area.width.saturating_sub(2);
let displayed_cursor = cursor_x.min(max_width);
f.set_cursor_position(ratatui::layout::Position::new(
search_area.x + displayed_cursor + 1,
search_area.y + 1,
));
}
}