Skip to content
This repository was archived by the owner on Jul 24, 2026. It is now read-only.

Commit 77d9560

Browse files
committed
feat(tui): show recents
1 parent 531f7f8 commit 77d9560

1 file changed

Lines changed: 58 additions & 27 deletions

File tree

crates/tui/src/ui/screens/transactions.rs

Lines changed: 58 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -133,9 +133,14 @@ fn render_header(frame: &mut Frame<'_>, area: Rect, state: &AppState) {
133133
}
134134

135135
fn render_list(frame: &mut Frame<'_>, area: Rect, state: &AppState, theme: &Theme) {
136+
let quick_height = if state.transactions.quick_active {
137+
5
138+
} else {
139+
4
140+
};
136141
let layout = Layout::default()
137142
.direction(Direction::Vertical)
138-
.constraints([Constraint::Length(4), Constraint::Min(0)])
143+
.constraints([Constraint::Length(quick_height), Constraint::Min(0)])
139144
.split(area);
140145

141146
render_quick_add(frame, layout[0], state, theme);
@@ -588,7 +593,11 @@ fn render_transaction_form(frame: &mut Frame<'_>, area: Rect, state: &AppState,
588593

589594
let bottom_layout = Layout::default()
590595
.direction(Direction::Vertical)
591-
.constraints([Constraint::Min(0), Constraint::Length(5)])
596+
.constraints([
597+
Constraint::Min(0),
598+
Constraint::Length(5),
599+
Constraint::Length(2),
600+
])
592601
.split(layout[1]);
593602

594603
let list_layout = Layout::default()
@@ -622,6 +631,7 @@ fn render_transaction_form(frame: &mut Frame<'_>, area: Rect, state: &AppState,
622631
);
623632

624633
render_category_list(frame, bottom_layout[1], state, theme);
634+
render_recents_footer(frame, bottom_layout[2], state, theme);
625635
}
626636

627637
fn render_picker_list(
@@ -823,6 +833,14 @@ fn render_filter_field(label: &str, value: &str, focused: bool, theme: &Theme) -
823833
])
824834
}
825835

836+
fn render_recents_footer(frame: &mut Frame<'_>, area: Rect, state: &AppState, theme: &Theme) {
837+
let Some(text) = recents_line(state) else {
838+
return;
839+
};
840+
let line = Line::from(Span::styled(text, Style::default().fg(theme.dim)));
841+
frame.render_widget(Paragraph::new(line), area);
842+
}
843+
826844
fn kind_toggle_chip(label: &str, enabled: bool, theme: &Theme) -> Span<'static> {
827845
let style = if enabled {
828846
Style::default()
@@ -883,32 +901,9 @@ fn render_quick_add(frame: &mut Frame<'_>, area: Rect, state: &AppState, theme:
883901
"Formato: 12.50 bar | +1000 stipendio | r 5.20 amazon | #tag opzionale",
884902
Style::default().fg(theme.dim),
885903
)));
886-
if !state.transactions.recent_categories.is_empty() {
887-
let recents = state
888-
.transactions
889-
.recent_categories
890-
.iter()
891-
.map(|cat| format!("#{cat}"))
892-
.collect::<Vec<_>>()
893-
.join(" ");
904+
if let Some(line) = recents_line(state) {
894905
lines.push(Line::from(Span::styled(
895-
format!("Recenti: {recents}"),
896-
Style::default().fg(theme.dim),
897-
)));
898-
}
899-
let recent_wallets = recent_wallet_names(state);
900-
if !recent_wallets.is_empty() {
901-
let list = recent_wallets.join(" • ");
902-
lines.push(Line::from(Span::styled(
903-
format!("Wallet recenti: {list}"),
904-
Style::default().fg(theme.dim),
905-
)));
906-
}
907-
let recent_flows = recent_flow_names(state);
908-
if !recent_flows.is_empty() {
909-
let list = recent_flows.join(" • ");
910-
lines.push(Line::from(Span::styled(
911-
format!("Flow recenti: {list}"),
906+
line,
912907
Style::default().fg(theme.dim),
913908
)));
914909
}
@@ -923,6 +918,42 @@ fn render_quick_add(frame: &mut Frame<'_>, area: Rect, state: &AppState, theme:
923918
frame.render_widget(widget, area);
924919
}
925920

921+
fn recents_line(state: &AppState) -> Option<String> {
922+
let mut parts = Vec::new();
923+
let categories = state
924+
.transactions
925+
.recent_categories
926+
.iter()
927+
.take(3)
928+
.map(|cat| format!("#{cat}"))
929+
.collect::<Vec<_>>();
930+
if !categories.is_empty() {
931+
parts.push(format!("Categorie: {}", categories.join(" ")));
932+
}
933+
934+
let wallets = recent_wallet_names(state)
935+
.into_iter()
936+
.take(3)
937+
.collect::<Vec<_>>();
938+
if !wallets.is_empty() {
939+
parts.push(format!("Wallet: {}", wallets.join(", ")));
940+
}
941+
942+
let flows = recent_flow_names(state)
943+
.into_iter()
944+
.take(3)
945+
.collect::<Vec<_>>();
946+
if !flows.is_empty() {
947+
parts.push(format!("Flow: {}", flows.join(", ")));
948+
}
949+
950+
if parts.is_empty() {
951+
None
952+
} else {
953+
Some(format!("Recenti: {}", parts.join(" • ")))
954+
}
955+
}
956+
926957
fn render_detail(frame: &mut Frame<'_>, area: Rect, state: &AppState, theme: &Theme) {
927958
let Some(detail) = &state.transactions.detail else {
928959
let block = Block::default()

0 commit comments

Comments
 (0)