diff options
| author | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-05-18 22:18:20 -0700 |
|---|---|---|
| committer | Tyler Hoang <tyler@tylerhoang.xyz> | 2026-05-18 22:18:20 -0700 |
| commit | 16d9eb4f864fe8c29a9dee57ec47f77b34ae0df4 (patch) | |
| tree | 36d56f7ed8bc5d893fafce807f7846e6c320b1cc /frontend | |
| parent | 566f59cb00958caa073279a7bb698e1ede48c0d4 (diff) | |
feat: wire Ratios subtab into FinancialsPage, move tab strip up from FinancialsCard
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/app/prism-shell.css | 6 | ||||
| -rw-r--r-- | frontend/components/prism/FinancialsCard.tsx | 20 | ||||
| -rw-r--r-- | frontend/components/prism/FinancialsPage.tsx | 68 |
3 files changed, 56 insertions, 38 deletions
diff --git a/frontend/app/prism-shell.css b/frontend/app/prism-shell.css index 424ebb3..4e65ced 100644 --- a/frontend/app/prism-shell.css +++ b/frontend/app/prism-shell.css @@ -1116,6 +1116,11 @@ overflow: hidden; } +.psm-fin-tab-bar { + border-bottom: 1px solid var(--line-1); + margin-bottom: 0; +} + .psm-fin-header { display: flex; align-items: stretch; @@ -1156,6 +1161,7 @@ display: flex; align-items: center; gap: var(--sp-1); + margin-left: auto; } .psm-fin-period-btn { diff --git a/frontend/components/prism/FinancialsCard.tsx b/frontend/components/prism/FinancialsCard.tsx index 94a6618..43a2dc2 100644 --- a/frontend/components/prism/FinancialsCard.tsx +++ b/frontend/components/prism/FinancialsCard.tsx @@ -9,16 +9,9 @@ type Props = { data: FinancialsResponse; statement: StatementKey; period: PeriodKey; - onChangeStatement: (s: StatementKey) => void; onChangePeriod: (p: PeriodKey) => void; }; -const STMT_LABELS: Record<StatementKey, string> = { - income: "INCOME", - balance: "BALANCE", - cash_flow: "CASH FLOW", -}; - function fmtFinVal(val: number | null | undefined, isMargin: boolean): string { if (val === null || val === undefined) return "—"; if (isMargin) return `${(val * 100).toFixed(1)}%`; @@ -70,7 +63,6 @@ export function FinancialsCard({ data, statement, period, - onChangeStatement, onChangePeriod, }: Props) { const stmt = data[statement]; @@ -79,18 +71,6 @@ export function FinancialsCard({ return ( <section className="psm-card psm-financials-card"> <div className="psm-fin-header"> - <div className="psm-fin-tabs"> - {(["income", "balance", "cash_flow"] as StatementKey[]).map((key) => ( - <button - key={key} - type="button" - className={`psm-fin-tab${statement === key ? " active" : ""}`} - onClick={() => onChangeStatement(key)} - > - {STMT_LABELS[key]} - </button> - ))} - </div> <div className="psm-fin-period"> {(["annual", "quarterly"] as PeriodKey[]).map((p) => ( <button diff --git a/frontend/components/prism/FinancialsPage.tsx b/frontend/components/prism/FinancialsPage.tsx index fcd2763..9a56f2c 100644 --- a/frontend/components/prism/FinancialsPage.tsx +++ b/frontend/components/prism/FinancialsPage.tsx @@ -4,10 +4,12 @@ import { api } from "@/lib/api"; import { buildKpis } from "@/lib/overview"; import { FinancialsCard } from "@/components/prism/FinancialsCard"; import { KPIStrip } from "@/components/prism/KPIStrip"; +import { RatiosPage } from "@/components/prism/RatiosPage"; import { TickerHeader } from "@/components/prism/TickerHeader"; import type { FinancialsResponse, TickerOverview } from "@/types/api"; -type StatementKey = "income" | "balance" | "cash_flow"; +type StatementKey = "income" | "balance" | "cash_flow" | "ratios"; +type FinancialStatementKey = Exclude<StatementKey, "ratios">; type PeriodKey = "annual" | "quarterly"; type FinState = "loading" | "ready" | "error"; @@ -18,6 +20,13 @@ type Props = { onToggleWatchlist: () => void; }; +const STATEMENT_LABELS: Record<StatementKey, string> = { + income: "INCOME", + balance: "BALANCE", + cash_flow: "CASH FLOW", + ratios: "RATIOS", +}; + export function FinancialsPage({ ticker, overview, isSaved, onToggleWatchlist }: Props) { const [statement, setStatement] = useState<StatementKey>("income"); const [period, setPeriod] = useState<PeriodKey>("annual"); @@ -26,6 +35,10 @@ export function FinancialsPage({ ticker, overview, isSaved, onToggleWatchlist }: const kpis = buildKpis(overview); useEffect(() => { + if (statement === "ratios") { + return; + } + let cancelled = false; setFinState("loading"); setData(null); @@ -45,28 +58,47 @@ export function FinancialsPage({ ticker, overview, isSaved, onToggleWatchlist }: return () => { cancelled = true; }; - }, [ticker, period]); + }, [ticker, period, statement]); return ( <> <TickerHeader overview={overview} isSaved={isSaved} onToggleWatchlist={onToggleWatchlist} /> <KPIStrip items={kpis} /> - {finState === "loading" && ( - <section className="psm-card psm-skeleton" style={{ minHeight: 320 }} /> - )} - {finState === "error" && ( - <section className="psm-card"> - <p className="psm-muted-copy">Financial statements unavailable for {ticker}.</p> - </section> - )} - {finState === "ready" && data && ( - <FinancialsCard - data={data} - statement={statement} - period={period} - onChangeStatement={setStatement} - onChangePeriod={setPeriod} - /> + <section className="psm-fin-tab-bar"> + <div className="psm-fin-tabs"> + {(["income", "balance", "cash_flow", "ratios"] as StatementKey[]).map((key) => ( + <button + key={key} + type="button" + className={`psm-fin-tab${statement === key ? " active" : ""}`} + onClick={() => setStatement(key)} + > + {STATEMENT_LABELS[key]} + </button> + ))} + </div> + </section> + {statement === "ratios" ? ( + <RatiosPage ticker={ticker} /> + ) : ( + <> + {finState === "loading" && ( + <section className="psm-card psm-skeleton" style={{ minHeight: 320 }} /> + )} + {finState === "error" && ( + <section className="psm-card"> + <p className="psm-muted-copy">Financial statements unavailable for {ticker}.</p> + </section> + )} + {finState === "ready" && data && ( + <FinancialsCard + data={data} + statement={statement as FinancialStatementKey} + period={period} + onChangePeriod={setPeriod} + /> + )} + </> )} </> ); |
