move loads into tabs

This commit is contained in:
Emil Lerch 2026-03-20 08:18:21 -07:00
parent 2bcb84dafa
commit 621a8db0df
Signed by: lobo
GPG key ID: A7B62D657EF764F8
3 changed files with 85 additions and 73 deletions

View file

@ -860,7 +860,7 @@ pub const App = struct {
}
}
fn rebuildOptionsRows(self: *App) void {
pub fn rebuildOptionsRows(self: *App) void {
self.options_rows.clearRetainingCapacity();
const chains = self.options_data orelse return;
const atm_price = if (chains.len > 0) chains[0].underlying_price orelse 0 else @as(f64, 0);
@ -1060,60 +1060,7 @@ pub const App = struct {
}
pub fn loadPerfData(self: *App) void {
self.perf_loaded = true;
self.freeCandles();
self.freeDividends();
self.trailing_price = null;
self.trailing_total = null;
self.trailing_me_price = null;
self.trailing_me_total = null;
self.candle_count = 0;
self.candle_first_date = null;
self.candle_last_date = null;
const candle_result = self.svc.getCandles(self.symbol) catch |err| {
switch (err) {
zfin.DataError.NoApiKey => self.setStatus("No API key. Set TWELVEDATA_API_KEY"),
zfin.DataError.FetchFailed => self.setStatus("Fetch failed (network error or rate limit)"),
else => self.setStatus("Error loading data"),
}
return;
};
self.candles = candle_result.data;
self.candle_timestamp = candle_result.timestamp;
const c = self.candles.?;
if (c.len == 0) {
self.setStatus("No data available for symbol");
return;
}
self.candle_count = c.len;
self.candle_first_date = c[0].date;
self.candle_last_date = c[c.len - 1].date;
const today = fmt.todayDate();
self.trailing_price = zfin.performance.trailingReturns(c);
self.trailing_me_price = zfin.performance.trailingReturnsMonthEnd(c, today);
if (self.svc.getDividends(self.symbol)) |div_result| {
self.dividends = div_result.data;
self.trailing_total = zfin.performance.trailingReturnsWithDividends(c, div_result.data);
self.trailing_me_total = zfin.performance.trailingReturnsMonthEndWithDividends(c, div_result.data, today);
} else |_| {}
self.risk_metrics = zfin.risk.trailingRisk(c);
// Try to load ETF profile (non-fatal, won't show for non-ETFs)
if (!self.etf_loaded) {
self.etf_loaded = true;
if (self.svc.getEtfProfile(self.symbol)) |etf_result| {
if (etf_result.data.isEtf()) {
self.etf_profile = etf_result.data;
}
} else |_| {}
}
self.setStatus(if (candle_result.source == .cached) "r/F5 to refresh" else "Fetched | r/F5 to refresh");
perf_tab.loadData(self);
}
fn loadEarningsData(self: *App) void {
@ -1121,24 +1068,7 @@ pub const App = struct {
}
fn loadOptionsData(self: *App) void {
self.options_loaded = true;
self.freeOptions();
const result = self.svc.getOptions(self.symbol) catch |err| {
switch (err) {
zfin.DataError.FetchFailed => self.setStatus("CBOE fetch failed (network error)"),
else => self.setStatus("Error loading options"),
}
return;
};
self.options_data = result.data;
self.options_timestamp = result.timestamp;
self.options_cursor = 0;
self.options_expanded = [_]bool{false} ** 64;
self.options_calls_collapsed = [_]bool{false} ** 64;
self.options_puts_collapsed = [_]bool{false} ** 64;
self.rebuildOptionsRows();
self.setStatus(if (result.source == .cached) "Cached (1hr TTL) | r/F5 to refresh" else "Fetched | r/F5 to refresh");
options_tab.loadData(self);
}
pub fn setStatus(self: *App, msg: []const u8) void {

View file

@ -8,6 +8,29 @@ const tui = @import("../tui.zig");
const App = tui.App;
const StyledLine = tui.StyledLine;
// Data loading
pub fn loadData(self: *App) void {
self.options_loaded = true;
self.freeOptions();
const result = self.svc.getOptions(self.symbol) catch |err| {
switch (err) {
zfin.DataError.FetchFailed => self.setStatus("CBOE fetch failed (network error)"),
else => self.setStatus("Error loading options"),
}
return;
};
self.options_data = result.data;
self.options_timestamp = result.timestamp;
self.options_cursor = 0;
self.options_expanded = [_]bool{false} ** 64;
self.options_calls_collapsed = [_]bool{false} ** 64;
self.options_puts_collapsed = [_]bool{false} ** 64;
self.rebuildOptionsRows();
self.setStatus(if (result.source == .cached) "Cached (1hr TTL) | r/F5 to refresh" else "Fetched | r/F5 to refresh");
}
// Rendering
pub fn buildStyledLines(self: *App, arena: std.mem.Allocator) ![]const StyledLine {

View file

@ -8,6 +8,65 @@ const tui = @import("../tui.zig");
const App = tui.App;
const StyledLine = tui.StyledLine;
// Data loading
pub fn loadData(self: *App) void {
self.perf_loaded = true;
self.freeCandles();
self.freeDividends();
self.trailing_price = null;
self.trailing_total = null;
self.trailing_me_price = null;
self.trailing_me_total = null;
self.candle_count = 0;
self.candle_first_date = null;
self.candle_last_date = null;
const candle_result = self.svc.getCandles(self.symbol) catch |err| {
switch (err) {
zfin.DataError.NoApiKey => self.setStatus("No API key. Set TWELVEDATA_API_KEY"),
zfin.DataError.FetchFailed => self.setStatus("Fetch failed (network error or rate limit)"),
else => self.setStatus("Error loading data"),
}
return;
};
self.candles = candle_result.data;
self.candle_timestamp = candle_result.timestamp;
const c = self.candles.?;
if (c.len == 0) {
self.setStatus("No data available for symbol");
return;
}
self.candle_count = c.len;
self.candle_first_date = c[0].date;
self.candle_last_date = c[c.len - 1].date;
const today = fmt.todayDate();
self.trailing_price = zfin.performance.trailingReturns(c);
self.trailing_me_price = zfin.performance.trailingReturnsMonthEnd(c, today);
if (self.svc.getDividends(self.symbol)) |div_result| {
self.dividends = div_result.data;
self.trailing_total = zfin.performance.trailingReturnsWithDividends(c, div_result.data);
self.trailing_me_total = zfin.performance.trailingReturnsMonthEndWithDividends(c, div_result.data, today);
} else |_| {}
self.risk_metrics = zfin.risk.trailingRisk(c);
// Try to load ETF profile (non-fatal, won't show for non-ETFs)
if (!self.etf_loaded) {
self.etf_loaded = true;
if (self.svc.getEtfProfile(self.symbol)) |etf_result| {
if (etf_result.data.isEtf()) {
self.etf_profile = etf_result.data;
}
} else |_| {}
}
self.setStatus(if (candle_result.source == .cached) "r/F5 to refresh" else "Fetched | r/F5 to refresh");
}
// Rendering
pub fn buildStyledLines(self: *App, arena: std.mem.Allocator) ![]const StyledLine {