summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-06-26 18:56:07 -0600
committermo khan <mo@mokhan.ca>2025-06-26 18:56:07 -0600
commit620fbf3f7515493c6b67032088a032c8bc6a1bc0 (patch)
treecbe29a9d74b6634374ea4289ddbfba8002fb8ea5
parent6f748dba5cec3509e01875deac3db4866912f02f (diff)
fix: prevent TUI crash from NaN/infinite float formatting
- Add is_finite() checks before formatting all float values - Handle NaN and infinite values by defaulting to 0.0 - Fixes crash when pressing Tab with invalid financial data - Ensures robust handling of edge cases in calculations This prevents the "formatting trait implementation returned an error" panic when displaying views with invalid floating point values. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
-rw-r--r--src/tui/dashboard.rs17
-rw-r--r--src/tui/ui.rs13
2 files changed, 18 insertions, 12 deletions
diff --git a/src/tui/dashboard.rs b/src/tui/dashboard.rs
index 5eed457..3c4d979 100644
--- a/src/tui/dashboard.rs
+++ b/src/tui/dashboard.rs
@@ -52,7 +52,7 @@ fn draw_net_worth(f: &mut Frame, app: &App, area: Rect) {
Line::from(vec![
Span::raw("$"),
Span::styled(
- format!("{:.0}", app.net_worth),
+ format!("{:.0}", if app.net_worth.is_finite() { app.net_worth } else { 0.0 }),
Style::default()
.fg(Color::Green)
.add_modifier(Modifier::BOLD),
@@ -60,13 +60,16 @@ fn draw_net_worth(f: &mut Frame, app: &App, area: Rect) {
]),
Line::from(vec![
Span::styled(
- format!("↑ ${:.0} ({:+.1}%)", net_worth_change, change_pct),
+ format!("↑ ${:.0} ({:+.1}%)",
+ if net_worth_change.is_finite() { net_worth_change } else { 0.0 },
+ if change_pct.is_finite() { change_pct } else { 0.0 }
+ ),
Style::default().fg(Color::Green),
),
]),
Line::from(""),
- Line::from(format!("💵 Cash: ${:.0}", app.cash_balance)),
- Line::from(format!("📈 Invest: ${:.0}", app.investment_balance)),
+ Line::from(format!("💵 Cash: ${:.0}", if app.cash_balance.is_finite() { app.cash_balance } else { 0.0 })),
+ Line::from(format!("📈 Invest: ${:.0}", if app.investment_balance.is_finite() { app.investment_balance } else { 0.0 })),
];
let net_worth = Paragraph::new(net_worth_text)
@@ -108,7 +111,7 @@ fn draw_cash_flow(f: &mut Frame, app: &App, area: Rect) {
.block(Block::default())
.gauge_style(Style::default().fg(Color::Green))
.ratio(income_ratio)
- .label(format!("Income: ${:.0}", app.income));
+ .label(format!("Income: ${:.0}", if app.income.is_finite() { app.income } else { 0.0 }));
// Expenses bar
let expense_ratio = if max_value > 0.0 { app.expenses / max_value } else { 0.0 };
@@ -116,7 +119,7 @@ fn draw_cash_flow(f: &mut Frame, app: &App, area: Rect) {
.block(Block::default())
.gauge_style(Style::default().fg(Color::Red))
.ratio(expense_ratio)
- .label(format!("Expenses: ${:.0}", app.expenses));
+ .label(format!("Expenses: ${:.0}", if app.expenses.is_finite() { app.expenses } else { 0.0 }));
// Net bar
let net_ratio = if max_value > 0.0 { net.abs() / max_value } else { 0.0 };
@@ -124,7 +127,7 @@ fn draw_cash_flow(f: &mut Frame, app: &App, area: Rect) {
.block(Block::default())
.gauge_style(Style::default().fg(if net >= 0.0 { Color::Cyan } else { Color::Magenta }))
.ratio(net_ratio)
- .label(format!("Net: {:+.0}", net));
+ .label(format!("Net: {:+.0}", if net.is_finite() { net } else { 0.0 }));
// Render frame and gauges
let frame = Block::default()
diff --git a/src/tui/ui.rs b/src/tui/ui.rs
index dba989a..ceb66b4 100644
--- a/src/tui/ui.rs
+++ b/src/tui/ui.rs
@@ -132,7 +132,7 @@ fn draw_budgets(f: &mut Frame, app: &App, area: Rect) {
Line::from(vec![
Span::raw(format!("{:<15} ", category)),
Span::styled(bar, Style::default().fg(status_color)),
- Span::raw(format!(" ${:.0}/${:.0}", spent, budget)),
+ Span::raw(format!(" ${:.0}/${:.0}", spent.max(0.0), budget.max(0.0))),
])
})
.collect();
@@ -152,12 +152,15 @@ fn draw_investments(f: &mut Frame, app: &App, area: Rect) {
let gain_pct = if total_book > 0.0 { (total_gain / total_book) * 100.0 } else { 0.0 };
let investment_text = vec![
- Line::from(format!("Total Market Value: ${:.2}", total_value)),
- Line::from(format!("Total Book Value: ${:.2}", total_book)),
+ Line::from(format!("Total Market Value: ${:.2}", if total_value.is_finite() { total_value } else { 0.0 })),
+ Line::from(format!("Total Book Value: ${:.2}", if total_book.is_finite() { total_book } else { 0.0 })),
Line::from(vec![
Span::raw("Unrealized Gain: "),
Span::styled(
- format!("${:.2} ({:+.1}%)", total_gain, gain_pct),
+ format!("${:.2} ({:+.1}%)",
+ if total_gain.is_finite() { total_gain } else { 0.0 },
+ if gain_pct.is_finite() { gain_pct } else { 0.0 }
+ ),
Style::default().fg(if total_gain >= 0.0 { Color::Green } else { Color::Red }),
),
]),
@@ -171,7 +174,7 @@ fn draw_investments(f: &mut Frame, app: &App, area: Rect) {
" {} ({:?}): ${:.2}",
portfolio.account_id,
portfolio.account_type,
- portfolio.total_market_value
+ if portfolio.total_market_value.is_finite() { portfolio.total_market_value } else { 0.0 }
)));
}