summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Hoang <tyler@tylerhoang.xyz>2026-05-18 00:33:39 -0700
committerTyler Hoang <tyler@tylerhoang.xyz>2026-05-18 00:33:39 -0700
commit7cb2492c748556af99f2b155a434b92f19461095 (patch)
treee64fa28a18676e9ca9bde0855184b12138f35cc6
parentfecdd44d856cdff8c8746551a3ae4e862a8752dc (diff)
feat: wire financials tab routing in Sidebar and page.tsx
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--frontend/app/page.tsx63
-rw-r--r--frontend/components/prism/Sidebar.tsx5
2 files changed, 49 insertions, 19 deletions
diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx
index 013b93d..6f7e5b6 100644
--- a/frontend/app/page.tsx
+++ b/frontend/app/page.tsx
@@ -4,6 +4,7 @@ import { FormEvent, Suspense, startTransition, useCallback, useEffect, useMemo,
import Image from "next/image";
import { useRouter, useSearchParams } from "next/navigation";
import { AppShell } from "@/components/prism/AppShell";
+import { FinancialsPage } from "@/components/prism/FinancialsPage";
import { ChartCard } from "@/components/prism/ChartCard";
import { KPIStrip } from "@/components/prism/KPIStrip";
import { Sidebar } from "@/components/prism/Sidebar";
@@ -29,6 +30,7 @@ function OverviewClient() {
const router = useRouter();
const searchParams = useSearchParams();
const selectedTicker = (searchParams.get("ticker") || "").toUpperCase();
+ const tab = searchParams.get("tab") || "overview";
const lastTickerRef = useRef("");
const [query, setQuery] = useState("");
@@ -72,11 +74,26 @@ function OverviewClient() {
setOverviewState("loading");
setChartState("loading");
+ const params = new URLSearchParams();
+ params.set("ticker", normalized);
+ if (tab !== "overview") params.set("tab", tab);
startTransition(() => {
- router.push(`/?ticker=${encodeURIComponent(normalized)}`);
+ router.push(`/?${params.toString()}`);
});
},
- [router]
+ [router, tab]
+ );
+
+ const navigateToTab = useCallback(
+ (key: string) => {
+ const params = new URLSearchParams();
+ if (selectedTicker) params.set("ticker", selectedTicker);
+ if (key !== "overview") params.set("tab", key);
+ startTransition(() => {
+ router.push(`/?${params.toString()}`);
+ });
+ },
+ [router, selectedTicker]
);
const clearTicker = useCallback(() => {
@@ -245,12 +262,13 @@ function OverviewClient() {
sidebar={
<Sidebar
navItems={OVERVIEW_NAV_ITEMS}
- selectedKey="overview"
+ selectedKey={tab}
currentTicker={selectedTicker}
watchlist={watchlist}
watchlistError={watchlistError}
onSelectTicker={navigateToTicker}
onRemoveTicker={removeFromWatchlist}
+ onSelectTab={navigateToTab}
/>
}
topbar={
@@ -271,22 +289,31 @@ function OverviewClient() {
{selectedTicker && overviewState === "invalid" ? <InvalidTickerState symbol={selectedTicker} onClear={clearTicker} /> : null}
{selectedTicker && overviewState === "error" ? <ErrorOverviewState message={overviewError || "Ticker data unavailable"} /> : null}
{overview && overviewState === "ready" ? (
- <>
- <TickerHeader overview={overview} onToggleWatchlist={addOrRemoveCurrentTicker} isSaved={isSaved} />
- <KPIStrip items={kpis} />
- <div className="psm-main-grid">
- <div className="psm-column">
- <ChartCard symbol={overview.profile.symbol} period={period} points={history} chartState={chartState} chartError={chartError} onChangePeriod={setPeriod} />
- <SignalCard overview={overview} />
- </div>
- <div className="psm-column">
- <DataStatusCard overview={overview} missingFields={missingFields} />
- <ProfileCard overview={overview} />
- <ShortInterestCard overview={overview} />
- <StatsCard overview={overview} />
+ tab === "financials" ? (
+ <FinancialsPage
+ ticker={selectedTicker}
+ overview={overview}
+ isSaved={isSaved}
+ onToggleWatchlist={addOrRemoveCurrentTicker}
+ />
+ ) : (
+ <>
+ <TickerHeader overview={overview} onToggleWatchlist={addOrRemoveCurrentTicker} isSaved={isSaved} />
+ <KPIStrip items={kpis} />
+ <div className="psm-main-grid">
+ <div className="psm-column">
+ <ChartCard symbol={overview.profile.symbol} period={period} points={history} chartState={chartState} chartError={chartError} onChangePeriod={setPeriod} />
+ <SignalCard overview={overview} />
+ </div>
+ <div className="psm-column">
+ <DataStatusCard overview={overview} missingFields={missingFields} />
+ <ProfileCard overview={overview} />
+ <ShortInterestCard overview={overview} />
+ <StatsCard overview={overview} />
+ </div>
</div>
- </div>
- </>
+ </>
+ )
) : null}
</AppShell>
);
diff --git a/frontend/components/prism/Sidebar.tsx b/frontend/components/prism/Sidebar.tsx
index 7f106d8..fb8ebcf 100644
--- a/frontend/components/prism/Sidebar.tsx
+++ b/frontend/components/prism/Sidebar.tsx
@@ -12,6 +12,7 @@ type Props = {
watchlistError: string | null;
onSelectTicker: (symbol: string) => void;
onRemoveTicker: (symbol: string) => void;
+ onSelectTab: (key: string) => void;
};
export function Sidebar({
@@ -21,7 +22,8 @@ export function Sidebar({
watchlist,
watchlistError,
onSelectTicker,
- onRemoveTicker
+ onRemoveTicker,
+ onSelectTab
}: Props) {
return (
<aside className="psm-side">
@@ -46,6 +48,7 @@ export function Sidebar({
type="button"
className={`psm-nav-item${active ? " active" : ""}${item.disabled ? " disabled" : ""}`}
disabled={item.disabled}
+ onClick={item.disabled ? undefined : () => onSelectTab(item.key)}
>
<span className={`psm-icon icon-${item.icon}`} aria-hidden />
<span className="psm-nav-copy">