/* FinPulse — live-data context + Settings modal. Uses FP_API layer. */
function curSym(c) { return window.FinnhubMappers.curSym(c); }
function relTime(unixSec) { return window.FinnhubMappers.relTime(unixSec); }
function mapNews(items) { return window.FinnhubMappers.mapNewsList(items); }
function buildLiveStock(symbol, q, profile, metric) {
return window.FinnhubMappers.mapStock(symbol, q, profile, metric);
}
function mcapM(m, cur) {
const s = curSym(cur);
if (!m || m <= 0) return '—';
if (m >= 1e6) return s + (m / 1e6).toFixed(2) + 'T';
if (m >= 1e3) return s + (m / 1e3).toFixed(1) + 'B';
return s + m.toFixed(0) + 'M';
}
const LiveCtx = React.createContext(null);
function useLive() { return React.useContext(LiveCtx); }
function LiveProvider({ children }) {
const api = window.FP_API.finnhub;
const market = window.FP_API.market;
const [key, setKeyState] = useState(api.getKey());
const [serverKey, setServerKey] = useState(false);
const [live, setLive] = useState(() => localStorage.getItem('fp-live') === '1' && api.hasKey());
const [connected, setConnected] = useState(false);
const [settingsOpen, setSettingsOpen] = useState(false);
const [rateLimit, setRateLimit] = useState(api.getRateLimit());
useEffect(() => {
let on = true;
async function initFinnhub() {
try {
const res = await fetch('/api/config');
if (res.ok) {
const cfg = await res.json();
if (cfg.finnhub && cfg.finnhub.available) {
api.setServerKeyAvailable(true);
if (on) setServerKey(true);
if (localStorage.getItem('fp-live') !== '0') {
localStorage.setItem('fp-live', '1');
if (on) setLive(true);
}
}
}
} catch (_) { /* offline */ }
if (!on) return;
if (api.hasKey()) {
try {
const ok = await api.test(null);
if (on) { setConnected(ok); setRateLimit(api.getRateLimit()); }
} catch (_) {
if (on) setConnected(false);
}
}
}
initFinnhub();
return () => { on = false; };
}, []);
function saveKey(k) { api.setKey(k); setKeyState(k); }
function setLiveMode(v) {
const on = v && api.hasKey();
setLive(on);
localStorage.setItem('fp-live', on ? '1' : '0');
}
const value = {
api,
market,
key,
connected,
setConnected,
live: live && connected,
liveRaw: live,
hasKey: !!key || serverKey,
rateLimit,
refreshRateLimit: () => setRateLimit(api.getRateLimit()),
saveKey,
setLiveMode,
openSettings: () => setSettingsOpen(true),
closeSettings: () => setSettingsOpen(false),
};
return (
Company Stock Price can pull live news and global data from Finnhub.
Keys are stored in this browser or loaded from src/config/local.js for local dev.