consolidate drip summary

This commit is contained in:
Emil Lerch 2026-03-19 13:04:20 -07:00
parent e29fb5b743
commit b162708055
Signed by: lobo
GPG key ID: A7B62D657EF764F8
3 changed files with 29 additions and 33 deletions

View file

@ -364,31 +364,15 @@ pub fn display(
const drip = fmt.aggregateDripLots(lots_for_sym.items);
if (!drip.st.isEmpty()) {
var avg_buf: [24]u8 = undefined;
var d1_buf: [10]u8 = undefined;
var d2_buf: [10]u8 = undefined;
var drip_buf: [128]u8 = undefined;
try cli.setFg(out, color, cli.CLR_MUTED);
try out.print(" ST: {d} DRIP lots, {d:.1} shares, avg {s} ({s} to {s})\n", .{
drip.st.lot_count,
drip.st.shares,
fmt.fmtMoneyAbs(&avg_buf, drip.st.avgCost()),
if (drip.st.first_date) |d| d.format(&d1_buf)[0..7] else "?",
if (drip.st.last_date) |d| d.format(&d2_buf)[0..7] else "?",
});
try out.print(" {s}\n", .{fmt.fmtDripSummary(&drip_buf, "ST", drip.st)});
try cli.reset(out, color);
}
if (!drip.lt.isEmpty()) {
var avg_buf2: [24]u8 = undefined;
var d1_buf2: [10]u8 = undefined;
var d2_buf2: [10]u8 = undefined;
var drip_buf2: [128]u8 = undefined;
try cli.setFg(out, color, cli.CLR_MUTED);
try out.print(" LT: {d} DRIP lots, {d:.1} shares, avg {s} ({s} to {s})\n", .{
drip.lt.lot_count,
drip.lt.shares,
fmt.fmtMoneyAbs(&avg_buf2, drip.lt.avgCost()),
if (drip.lt.first_date) |d| d.format(&d1_buf2)[0..7] else "?",
if (drip.lt.last_date) |d| d.format(&d2_buf2)[0..7] else "?",
});
try out.print(" {s}\n", .{fmt.fmtDripSummary(&drip_buf2, "LT", drip.lt)});
try cli.reset(out, color);
}
}

View file

@ -427,6 +427,23 @@ pub fn aggregateDripLots(lots: []const Lot) DripAggregation {
return result;
}
/// Format a DRIP summary line: "ST: 12 DRIP lots, 3.5 shares, avg $45.67 (2023-01 to 2024-06)"
pub fn fmtDripSummary(buf: []u8, label: []const u8, summary: DripSummary) []const u8 {
var avg_buf: [24]u8 = undefined;
var d1_buf: [10]u8 = undefined;
var d2_buf: [10]u8 = undefined;
const d1: []const u8 = if (summary.first_date) |d| d.format(&d1_buf)[0..7] else "?";
const d2: []const u8 = if (summary.last_date) |d| d.format(&d2_buf)[0..7] else "?";
return std.fmt.bufPrint(buf, "{s}: {d} DRIP lots, {d:.1} shares, avg {s} ({s} to {s})", .{
label,
summary.lot_count,
summary.shares,
fmtMoneyAbs(&avg_buf, summary.avgCost()),
d1,
d2,
}) catch "?";
}
// Shared rendering helpers (CLI + TUI)
/// Layout constants for analysis breakdown views.

View file

@ -867,20 +867,15 @@ pub fn drawContent(self: *App, arena: std.mem.Allocator, buf: []vaxis.Cell, widt
}
},
.drip_summary => {
const label_str: []const u8 = if (row.drip_is_lt) "LT" else "ST";
var drip_avg_buf: [24]u8 = undefined;
var drip_d1_buf: [10]u8 = undefined;
var drip_d2_buf: [10]u8 = undefined;
const drip_d1: []const u8 = if (row.drip_date_first) |d| d.format(&drip_d1_buf)[0..7] else "?";
const drip_d2: []const u8 = if (row.drip_date_last) |d| d.format(&drip_d2_buf)[0..7] else "?";
const text = try std.fmt.allocPrint(arena, " {s}: {d} DRIP lots, {d:.1} shares, avg {s} ({s} to {s})", .{
label_str,
row.drip_lot_count,
row.drip_shares,
fmt.fmtMoneyAbs(&drip_avg_buf, row.drip_avg_cost),
drip_d1,
drip_d2,
var drip_buf: [128]u8 = undefined;
const drip_text = fmt.fmtDripSummary(&drip_buf, if (row.drip_is_lt) "LT" else "ST", .{
.lot_count = row.drip_lot_count,
.shares = row.drip_shares,
.cost = row.drip_shares * row.drip_avg_cost,
.first_date = row.drip_date_first,
.last_date = row.drip_date_last,
});
const text = try std.fmt.allocPrint(arena, " {s}", .{drip_text});
const drip_style = if (is_cursor) th.selectStyle() else th.mutedStyle();
try lines.append(arena, .{ .text = text, .style = drip_style });
},