/* FinPulse app shell. Exports to window. */ const NAV_ITEMS = [ { key: 'markets', label: 'Markets', icon: 'markets' }, { key: 'stocks', label: 'Stocks', icon: 'stocks' }, { key: 'screener', label: 'Screener', icon: 'screener' }, { key: 'indices', label: 'Indices', icon: 'indices' }, { key: 'funds', label: 'Mutual Funds', icon: 'funds' }, { key: 'ipo', label: 'IPO', icon: 'ipo' }, { key: 'news', label: 'News', icon: 'news' }, { key: 'calc', label: 'Calculators', icon: 'calc' }, ]; function TickerBar({ stocks, onOpenStock }) { const Item = ({ s }) => ( ); return (
{stocks.map((s) => )} {stocks.map((s) => )}
); } function Brand({ mobile, onHome }) { const B = window.CSP_BRAND || { name: 'Company Stock Price', shortName: 'CSP', domain: 'companystockprice.com' }; const inner = ( <>
Company Stock Price {!mobile && {B.domain}}
); if (mobile) { return ( ); } return ( ); } function Sidebar({ current, onNav, drawerOpen, onCloseDrawer, onHome }) { return ( ); } function userInitials(name) { const parts = String(name || '').trim().split(/\s+/).filter(Boolean); if (!parts.length) return null; if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase(); return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase(); } function Topbar({ theme, onToggleTheme, onHamburger, onOpenSearch, onHome }) { const gate = typeof useUsageGate === 'function' ? useUsageGate() : null; const showProfile = gate && gate.signedIn; return (
{ e.target.blur(); onOpenSearch(); }} readOnly /> ⌘K
{showProfile && (
{userInitials(gate.userName) || }
)}
); } const BOTTOM_ITEMS = [ { key: 'markets', label: 'Markets', icon: 'markets' }, { key: 'stocks', label: 'Stocks', icon: 'stocks' }, { key: 'news', label: 'News', icon: 'news' }, { key: 'more', label: 'More', icon: 'more' }, ]; function BottomNav({ current, onNav }) { return ( ); } function SearchOverlay({ open, onClose, onOpenStock }) { const L = useLive(); const MD = useMarketData(); const [q, setQ] = useState(''); const [results, setResults] = useState([]); const [busy, setBusy] = useState(false); const [loadingSym, setLoadingSym] = useState(null); const [err, setErr] = useState(''); useEffect(() => { if (open) { setQ(''); setResults([]); setErr(''); } }, [open]); useEffect(() => { if (!q.trim()) { setResults([]); return; } setBusy(true); setErr(''); const id = setTimeout(async () => { try { const local = L.market.searchLocal(q.trim(), MD.stocks, 8); if (L.hasKey) { const remote = await L.market.searchSymbols(q.trim(), 6, MD.stocks); const seen = new Set(local.map((r) => r.symbol)); setResults([...local, ...remote.filter((r) => !seen.has(r.symbol))]); L.refreshRateLimit(); } else { setResults(local); } } catch (e) { setResults(L.market.searchLocal(q.trim(), MD.stocks, 12)); } finally { setBusy(false); } }, 300); return () => clearTimeout(id); }, [q, L.hasKey, MD.stocks]); async function openLive(symbol) { setLoadingSym(symbol); setErr(''); try { const sym = String(symbol || ''); const local = MD.stocks.find((s) => s.symbol === sym || s.ticker === sym.replace(/\.NS$/i, '')); if (local) { onOpenStock(local); onClose(); return; } onOpenStock(await L.market.getStock(symbol)); L.refreshRateLimit(); onClose(); } catch (e) { setErr(e.code === 'RATE_LIMIT' ? 'Rate limit — wait a moment' : apiErrorMessage(e)); } finally { setLoadingSym(null); } } if (!open) return null; const recent = [...MD.stocks].sort((a, b) => Math.abs(b.chg) - Math.abs(a.chg)).slice(0, 10).map((s) => s.ticker); return (
setQ(e.target.value)} placeholder="Search NSE stocks (Reliance, TCS…) or US symbols" />
{err &&
{err}
} {q ? ( busy ? (
{[0, 1, 2, 3].map((i) => (
))}
) : results.length ? results.map((r) => (
openLive(r.symbol)}> {r.displaySymbol || r.symbol} {r.description} {loadingSym === r.symbol ? loading… : }
)) :
No matches for "{q}"
) : ( <>
Popular symbols
{recent.map((r, i) => (
openLive(r)} style={{ cursor: 'pointer' }}> {r} {loadingSym === r ? loading… : }
))} )}
); } function Footer({ onNav }) { const B = window.CSP_BRAND || { legalName: 'Company Stock Price', copyrightYear: 2026, domain: 'companystockprice.com' }; const links = [ { key: 'about', label: 'About' }, { key: 'terms', label: 'Terms' }, { key: 'privacy', label: 'Privacy' }, { key: 'disclaimer', label: 'Disclaimer' }, ]; return ( ); } Object.assign(window, { NAV_ITEMS, TickerBar, Sidebar, Topbar, BottomNav, SearchOverlay, Footer });