diff options
author | Navan Chauhan <navanchauhan@gmail.com> | 2025-04-27 20:44:14 -0600 |
---|---|---|
committer | Navan Chauhan <navanchauhan@gmail.com> | 2025-04-27 20:44:14 -0600 |
commit | 2bc0555caa595967a28593aec2abd52500c5ddf9 (patch) | |
tree | f64875ade75adb690e93bd5b5d47e25d9b0df46a /client/src/MarketDataPage.jsx | |
parent | ca784c19f48814094c91a2c1a5652c20ca381c13 (diff) |
switch markets for market data
Diffstat (limited to 'client/src/MarketDataPage.jsx')
-rw-r--r-- | client/src/MarketDataPage.jsx | 141 |
1 files changed, 82 insertions, 59 deletions
diff --git a/client/src/MarketDataPage.jsx b/client/src/MarketDataPage.jsx index 3ffa099..76d8284 100644 --- a/client/src/MarketDataPage.jsx +++ b/client/src/MarketDataPage.jsx @@ -1,73 +1,99 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useContext } from 'react'; import { Typography, Spin, Message, Card, Grid } from '@arco-design/web-react'; import '@arco-design/web-react/dist/css/arco.css'; import { initVChartArcoTheme } from '@visactor/vchart-arco-theme'; import { VChart } from '@visactor/react-vchart'; import API_BASE_URL from './config'; +import { MarketContext, MARKET_FULL_NAMES } from './App'; + const { Row, Col } = Grid; -function MarketDataPage() { - const [fiveMinData, setFiveMinData] = useState([]); - const [dayAheadData, setDayAheadData] = useState([]); - const [loading, setLoading] = useState(true); - const [fiveMinLastUpdated, setFiveMinLastUpdated] = useState(null); - const [dayAheadLastUpdated, setDayAheadLastUpdated] = useState(null); +function TimeAgo({ timestamp, prefix }) { const [now, setNow] = useState(new Date()); useEffect(() => { - const fetchFiveMinData = async () => { - try { - const res = await fetch(`${API_BASE_URL}/market/real-time`); - if (!res.ok) throw new Error('Failed to fetch real-time data'); - const json = await res.json(); - setFiveMinData(json); - setFiveMinLastUpdated(new Date()); - } catch (err) { - console.error(err); - Message.error('Failed to load real-time market data.'); - } - }; + const timer = setInterval(() => setNow(new Date()), 1000); + return () => clearInterval(timer); + }, []); - const fetchDayAheadData = async () => { - try { - const res = await fetch(`${API_BASE_URL}/market/day-ahead`); - if (!res.ok) throw new Error('Failed to fetch day-ahead data'); - const json = await res.json(); - setDayAheadData(json); - setDayAheadLastUpdated(new Date()); - } catch (err) { - console.error(err); - Message.error('Failed to load day-ahead market data.'); - } - }; + const formatTimeAgo = () => { + if (!timestamp) return ''; + const seconds = Math.floor((now - timestamp) / 1000); + if (seconds < 60) return `${seconds} sec ago`; + const minutes = Math.floor(seconds / 60); + if (minutes < 60) return `${minutes} min ago`; + const hours = Math.floor(minutes / 60); + return `${hours} hr ago`; + }; - const initialize = async () => { - setLoading(true); - await Promise.all([fetchFiveMinData(), fetchDayAheadData()]); - setLoading(false); + return ( + <Typography.Text type="secondary" style={{ display: 'block' }}> + {prefix}: {formatTimeAgo()} + </Typography.Text> + ); +} - initVChartArcoTheme({ - defaultMode: 'light', - isWatchingMode: true - }); - }; - initialize(); +function MarketDataPage() { + const { selectedMarket } = useContext(MarketContext); + const [fiveMinData, setFiveMinData] = useState([]); + const [dayAheadData, setDayAheadData] = useState([]); + const [loading, setLoading] = useState(true); + const [fiveMinLastUpdated, setFiveMinLastUpdated] = useState(null); + const [dayAheadLastUpdated, setDayAheadLastUpdated] = useState(null); + const [now, setNow] = useState(new Date()); + + useEffect(() => { + const fetchFiveMinData = async () => { + try { + const res = await fetch(`${API_BASE_URL}/market/real-time?market=${selectedMarket}`); + if (!res.ok) throw new Error('Failed to fetch real-time data'); + const json = await res.json(); + setFiveMinData(json); + setFiveMinLastUpdated(new Date()); + } catch (err) { + console.error(err); + Message.error('Failed to load real-time market data.'); + } + }; + + const fetchDayAheadData = async () => { + try { + const res = await fetch(`${API_BASE_URL}/market/day-ahead?market=${selectedMarket}`); + if (!res.ok) throw new Error('Failed to fetch day-ahead data'); + const json = await res.json(); + setDayAheadData(json); + setDayAheadLastUpdated(new Date()); + } catch (err) { + console.error(err); + Message.error('Failed to load day-ahead market data.'); + } + }; - const fiveMinInterval = setInterval(fetchFiveMinData, 5 * 60 * 1000); // 5 minutes - const dayAheadInterval = setInterval(fetchDayAheadData, 60 * 60 * 1000); // 1 hour + const initialize = async () => { + setLoading(true); + await Promise.all([fetchFiveMinData(), fetchDayAheadData()]); + setLoading(false); - const timer = setInterval(() => { - setNow(new Date()); - }, 1000); + initVChartArcoTheme({ + defaultMode: 'light', + isWatchingMode: true + }); + }; - return () => { - clearInterval(fiveMinInterval); - clearInterval(dayAheadInterval); - clearInterval(timer); - }; - }, []); + initialize(); + + const fiveMinInterval = setInterval(fetchFiveMinData, 5 * 60 * 1000); // 5 minutes + const dayAheadInterval = setInterval(fetchDayAheadData, 60 * 60 * 1000); // 1 hour + const timer = setInterval(() => setNow(new Date()), 1000); + + return () => { + clearInterval(fiveMinInterval); + clearInterval(dayAheadInterval); + clearInterval(timer); + }; + }, [selectedMarket]); const getChartSpec = (data, title) => ({ type: 'line', @@ -151,18 +177,15 @@ function MarketDataPage() { return ( <div style={{ padding: 20, backgroundColor: 'var(--color-fill-2)' }}> - <Typography.Title heading={4}>Market Data Visualization</Typography.Title> - <Typography.Text type="secondary" style={{ marginTop: 10, display: 'block' }}> - Real-Time Data Last Updated: {formatTimeAgo(fiveMinLastUpdated)} - </Typography.Text> - <Typography.Text type="secondary" style={{ marginBottom: 20, display: 'block' }}> - Day-Ahead Data Last Updated: {formatTimeAgo(dayAheadLastUpdated)} - </Typography.Text> + <Typography.Title heading={4}>Market Data for {MARKET_FULL_NAMES[selectedMarket]}</Typography.Title> + {loading ? ( <Spin /> ) : ( <> + <TimeAgo timestamp={fiveMinLastUpdated} prefix="Real-Time Data Last Updated" /> + <TimeAgo timestamp={dayAheadLastUpdated} prefix="Day-Ahead Data Last Updated" /> <Row gutter={24} style={{ marginTop: 20, marginBottom: 20 }}> <Col xs={12} md={6} style={{ marginTop: 10}}> <Card style={{ textAlign: 'center' }} title="Avg Real-Time LMP ($/MWh)"> |