summaryrefslogtreecommitdiff
path: root/frontend/app/page.tsx
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2026-05-19 00:41:35 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2026-05-19 00:41:35 -0700
commit927a77d68b138778690d380fe7931cc37ce06c9e (patch)
tree050e8bec85837dd6db98188c88349959a1925040 /frontend/app/page.tsx
parent0a6fa2a6566a6d20b9cd587f1d188869971871c5 (diff)
feat: fetch valuation on overview tab, add DCF block to ValuationOverviewCard
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'frontend/app/page.tsx')
-rw-r--r--frontend/app/page.tsx35
1 files changed, 33 insertions, 2 deletions
diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx
index 150aaff..07bdfa4 100644
--- a/frontend/app/page.tsx
+++ b/frontend/app/page.tsx
@@ -17,10 +17,11 @@ import { VolumeCard } from "@/components/prism/VolumeCard";
import { ApiError, api } from "@/lib/api";
import { deltaClass, fmtNumber, fmtPct } from "@/lib/format";
import { buildKpis, limitIndices, marketClock, OVERVIEW_NAV_ITEMS, signalTone } from "@/lib/overview";
-import type { HistoryPoint, MarketIndex, SearchResult, TickerOverview, WatchlistResponse } from "@/types/api";
+import type { HistoryPoint, MarketIndex, SearchResult, TickerOverview, ValuationResponse, WatchlistResponse } from "@/types/api";
type LoadState = "idle" | "loading" | "ready" | "invalid" | "error";
type ChartState = "idle" | "loading" | "ready" | "error";
+type ValState = "idle" | "loading" | "ready" | "error";
export default function OverviewPage() {
return (
@@ -49,6 +50,8 @@ function OverviewClient() {
const [overviewError, setOverviewError] = useState<string | null>(null);
const [chartState, setChartState] = useState<ChartState>("idle");
const [chartError, setChartError] = useState<string | null>(null);
+ const [valuation, setValuation] = useState<ValuationResponse | null>(null);
+ const [valState, setValState] = useState<ValState>("idle");
const [watchlistError, setWatchlistError] = useState<string | null>(null);
const [clockSnapshot, setClockSnapshot] = useState(() => marketClock());
@@ -229,6 +232,34 @@ function OverviewClient() {
};
}, [selectedTicker, period]);
+ useEffect(() => {
+ if (!selectedTicker) {
+ setValuation(null);
+ setValState("idle");
+ return;
+ }
+
+ let cancelled = false;
+ setValState("loading");
+ setValuation(null);
+
+ api
+ .valuation(selectedTicker)
+ .then((res) => {
+ if (!cancelled) {
+ setValuation(res);
+ setValState("ready");
+ }
+ })
+ .catch(() => {
+ if (!cancelled) setValState("error");
+ });
+
+ return () => {
+ cancelled = true;
+ };
+ }, [selectedTicker]);
+
async function onSearchSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
if (results[0]) {
@@ -318,7 +349,7 @@ function OverviewClient() {
<div className="psm-column">
<ProfileCard overview={overview} />
<ShortInterestCard overview={overview} />
- <ValuationOverviewCard overview={overview} />
+ <ValuationOverviewCard overview={overview} valuation={valuation} valState={valState} />
<QualityCard overview={overview} />
</div>
</div>