diff options
| author | hc <hc@email.ch> | 2024-09-12 11:46:51 +0800 |
|---|---|---|
| committer | hc <hc@email.ch> | 2024-09-12 11:46:51 +0800 |
| commit | fabefacd8da4932c9a5e8b4aec33d196c290d33b (patch) | |
| tree | 58f775cff291903a091ed3d4a63265ad44705614 /btcdashboard/App.js | |
Diffstat (limited to 'btcdashboard/App.js')
| -rw-r--r-- | btcdashboard/App.js | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/btcdashboard/App.js b/btcdashboard/App.js new file mode 100644 index 0000000..838ab4f --- /dev/null +++ b/btcdashboard/App.js | |||
| @@ -0,0 +1,81 @@ | |||
| 1 | import React, { useState, useEffect } from 'react'; | ||
| 2 | import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts'; | ||
| 3 | |||
| 4 | const App = () => { | ||
| 5 | const [prices, setPrices] = useState([]); | ||
| 6 | const [rawData, setRawData] = useState(''); | ||
| 7 | const [error, setError] = useState(null); | ||
| 8 | |||
| 9 | const testingString = "hiiii"; | ||
| 10 | |||
| 11 | useEffect(() => { | ||
| 12 | const fetchPrices = async () => { | ||
| 13 | try { | ||
| 14 | console.log('Fetching prices...'); | ||
| 15 | const response = await fetch('/api/prices', { | ||
| 16 | method: 'GET', | ||
| 17 | headers: { | ||
| 18 | 'Content-Type': 'application/json', | ||
| 19 | }, | ||
| 20 | }); | ||
| 21 | console.log('Response status:', response.status); | ||
| 22 | console.log('Response headers:', response.headers); | ||
| 23 | if (!response.ok) { | ||
| 24 | throw new Error(`HTTP error! status: ${response.status}`); | ||
| 25 | } | ||
| 26 | const data = await response.json(); | ||
| 27 | console.log('Fetched data:', data); | ||
| 28 | setPrices(data); | ||
| 29 | setRawData(JSON.stringify(data, null, 2)); | ||
| 30 | setError(null); | ||
| 31 | } catch (error) { | ||
| 32 | console.error('Failed to fetch prices:', error); | ||
| 33 | setError(error.toString()); | ||
| 34 | setRawData(''); | ||
| 35 | } | ||
| 36 | }; | ||
| 37 | fetchPrices(); | ||
| 38 | const interval = setInterval(fetchPrices, 5000); | ||
| 39 | return () => clearInterval(interval); | ||
| 40 | }, []); | ||
| 41 | |||
| 42 | // prep data | ||
| 43 | const chartData = prices.map(item => { | ||
| 44 | const parsedItem = JSON.parse(item); | ||
| 45 | return { | ||
| 46 | price: parsedItem.price, | ||
| 47 | time: new Date(parsedItem.timestamp * 1000).toLocaleTimeString() | ||
| 48 | }; | ||
| 49 | }).reverse(); // show oldest data first | ||
| 50 | |||
| 51 | return ( | ||
| 52 | <div> | ||
| 53 | <h1>price</h1> | ||
| 54 | <p>test stuff: {testingString}</p> | ||
| 55 | {error && <p>Error: {error}</p>} | ||
| 56 | <pre>{rawData}</pre> | ||
| 57 | |||
| 58 | <h2>Price Graph</h2> | ||
| 59 | <ResponsiveContainer width="100%" height={400}> | ||
| 60 | <LineChart | ||
| 61 | data={chartData} | ||
| 62 | margin={{ | ||
| 63 | top: 5, | ||
| 64 | right: 30, | ||
| 65 | left: 20, | ||
| 66 | bottom: 5, | ||
| 67 | }} | ||
| 68 | > | ||
| 69 | <CartesianGrid strokeDasharray="3 3" /> | ||
| 70 | <XAxis dataKey="time" /> | ||
| 71 | <YAxis domain={['auto', 'auto']} /> | ||
| 72 | <Tooltip /> | ||
| 73 | <Legend /> | ||
| 74 | <Line type="monotone" dataKey="price" stroke="#8884d8" activeDot={{ r: 8 }} /> | ||
| 75 | </LineChart> | ||
| 76 | </ResponsiveContainer> | ||
| 77 | </div> | ||
| 78 | ); | ||
| 79 | }; | ||
| 80 | |||
| 81 | export default App; | ||
