import type { ReactElement } from 'react' import { useData, usePublish, type PanelRef } from '@jaspers-ai/sdk' import { display as d } from './format' import { lineValue, type Frequency, type LineKind, type Statement } from './server/financials' import { Bar, Empty, Loading, Section, SymbolField, usePanelStateValue, useStateWriter } from './shared' import { list, record, text } from './values' import { financialsOutput, readFinancialsState, type FinancialsState } from './views' import './styles.css' // One company's statement: line items down, periods across, latest first, the lines that matter in // bold. The toggles write `statement` and `frequency`; a balance sheet has no trailing twelve months, // so choosing one while TTM is on moves to annual. const STATEMENTS: [Statement, string][] = [ ['income', 'Income'], ['balance', 'Balance sheet'], ['cashflow', 'Cash flow'], ] const FREQUENCIES: [Frequency, string][] = [ ['annual', 'Annual'], ['quarterly', 'Quarterly'], ['trailing', 'TTM'], ] export function FinancialsView({ panel }: { panel: PanelRef }): ReactElement { const state = usePanelStateValue(panel) const write = useStateWriter(panel) if (state === undefined) return const read = readFinancialsState(state) return (
write([['symbol', symbol]])} /> write(statement === 'balance' && read.frequency === 'trailing' ? [['frequency', 'annual'], ['statement', statement]] : [['statement', statement]])} /> write([['frequency', frequency]])} />
{read.symbol ? ( ) : ( Enter a symbol: AAPL, MSFT, 7203.T. )}
) } function Toggle({ label, options, value, disabled = [], onChange, }: { label: string options: [T, string][] value: T disabled?: T[] onChange: (value: T) => void }): ReactElement { return (
{options.map(([key, name]) => ( ))}
) } function Statement({ panel, state }: { panel: PanelRef; state: FinancialsState }): ReactElement { const run = useData('yfinance/financials', { symbol: state.symbol, statement: state.statement, frequency: state.frequency }) usePublish(panel, financialsOutput(state, run)) const periods = list(run.meta['periods']).map(text).filter((p): p is string => p !== null) const rows = run.data ?? [] const currency = text(run.meta['currency']) const name = STATEMENTS.find(([key]) => key === state.statement)![1] const every = FREQUENCIES.find(([key]) => key === state.frequency)![1] return (
{periods.map((p) => ( ))} {rows.map((row) => { const values = record(row['values']) ?? {} const kind = (text(row['kind']) ?? 'money') as LineKind return ( {periods.map((p) => { const value = typeof values[p] === 'number' ? (values[p] as number) : null return ( ) })} ) })}
{state.frequency === 'trailing' ? 'Twelve months to' : 'Period ended'} {p}
{text(row['label'])} {lineValue(kind, value, d)}
) }