diff options
Diffstat (limited to 'client/src/components/BidsPage.jsx')
-rw-r--r-- | client/src/components/BidsPage.jsx | 134 |
1 files changed, 82 insertions, 52 deletions
diff --git a/client/src/components/BidsPage.jsx b/client/src/components/BidsPage.jsx index 2b97e99..3e596f0 100644 --- a/client/src/components/BidsPage.jsx +++ b/client/src/components/BidsPage.jsx @@ -1,56 +1,75 @@ -import React, { useEffect, useState } from 'react'; -import { Table, Typography, Spin, Message, Card, Empty, Badge } from '@arco-design/web-react'; -import { IconArrowRise, IconArrowFall } from '@arco-design/web-react/icon'; -import '@arco-design/web-react/dist/css/arco.css'; -import API_BASE_URL from '../config'; +import React, { useEffect, useState } from "react"; +import { + Table, + Typography, + Spin, + Message, + Card, + Empty, + Badge, +} from "@arco-design/web-react"; +import { IconArrowRise, IconArrowFall } from "@arco-design/web-react/icon"; +import "@arco-design/web-react/dist/css/arco.css"; +import API_BASE_URL from "../config"; const columns = (bids) => [ { - title: 'Timestamp', - dataIndex: 'timestamp', + title: "Timestamp", + dataIndex: "timestamp", sorter: (a, b) => new Date(a.timestamp) - new Date(b.timestamp), render: (val) => new Date(val).toLocaleString(), width: 180, }, { - title: 'Quantity (MW)', - dataIndex: 'quantity', + title: "Quantity (MW)", + dataIndex: "quantity", sorter: (a, b) => a.quantity - b.quantity, render: (val) => val.toFixed(2), width: 180, }, { - title: 'Price ($/MWh)', - dataIndex: 'price', + title: "Price ($/MWh)", + dataIndex: "price", sorter: (a, b) => a.price - b.price, render: (val) => `$${val.toFixed(2)}`, width: 180, }, { - title: 'Status', - dataIndex: 'status', + title: "Status", + dataIndex: "status", sorter: (a, b) => a.status.localeCompare(b.status), filters: [ - { text: 'Submitted', value: 'Submitted' }, - { text: 'Success', value: 'Success' }, - { text: 'Fail', value: 'Fail' }, + { text: "Submitted", value: "Submitted" }, + { text: "Success", value: "Success" }, + { text: "Fail", value: "Fail" }, ], onFilter: (value, record) => record.status === value, render: (val) => ( - <Badge status={val === 'Success' ? 'success' : val === 'Fail' ? 'error' : 'processing'} text={val} /> + <Badge + status={ + val === "Success" + ? "success" + : val === "Fail" + ? "error" + : "processing" + } + text={val} + /> ), width: 180, }, { - title: 'PnL', - dataIndex: 'pnl', + title: "PnL", + dataIndex: "pnl", sorter: (a, b) => (a.pnl || 0) - (b.pnl || 0), render: (val) => { - if (val === null) return 'N/A'; + if (val === null) return "N/A"; const isProfit = val >= 0; - const color = isProfit ? 'green' : 'red'; + const color = isProfit ? "green" : "red"; return ( - <Typography.Text style={{ color, display: 'flex', alignItems: 'center', gap: 4 }}> + <Typography.Text + style={{ color, display: "flex", alignItems: "center", gap: 4 }} + > {isProfit ? <IconArrowRise /> : <IconArrowFall />} {val.toFixed(2)} </Typography.Text> @@ -59,13 +78,13 @@ const columns = (bids) => [ width: 180, }, { - title: 'Market', - dataIndex: 'market', + title: "Market", + dataIndex: "market", sorter: (a, b) => a.market.localeCompare(b.market), filters: [ - { text: 'ISONE', value: 'ISONE' }, - { text: 'NYISO', value: 'NYISO' }, - { text: 'MISO', value: 'MISO' }, + { text: "ISONE", value: "ISONE" }, + { text: "NYISO", value: "NYISO" }, + { text: "MISO", value: "MISO" }, ], onFilter: (value, record) => record.market === value, render: (val) => val, @@ -80,20 +99,30 @@ function BidsPage() { useEffect(() => { fetch(`${API_BASE_URL}/bids/`) .then((res) => { - if (!res.ok) throw new Error('Failed to fetch bids'); + if (!res.ok) throw new Error("Failed to fetch bids"); return res.json(); }) .then((json) => setBids(json)) .catch((err) => { console.error(err); - Message.error('Failed to load bids.'); + Message.error("Failed to load bids."); }) .finally(() => setLoading(false)); }, []); return ( - <div style={{ padding: 20, backgroundColor: 'var(--color-fill-2)', minHeight: 'calc(100vh - 150px)', animation: 'fadeSlideIn 0.6s ease' }}> - <Typography.Title heading={3} style={{ textAlign: 'center', marginBottom: 20 }}> + <div + style={{ + padding: 20, + backgroundColor: "var(--color-fill-2)", + minHeight: "calc(100vh - 150px)", + animation: "fadeSlideIn 0.6s ease", + }} + > + <Typography.Title + heading={3} + style={{ textAlign: "center", marginBottom: 20 }} + > Your Submitted Bids </Typography.Title> @@ -101,37 +130,38 @@ function BidsPage() { style={{ marginTop: 16, borderRadius: 16, - boxShadow: '0 8px 24px rgba(0,0,0,0.08)', - background: 'linear-gradient(135deg, rgba(255,255,255,0.95) 0%, rgba(245,245,245,0.95) 100%)', - backdropFilter: 'blur(8px)', - overflow: 'hidden', - padding: 20 + boxShadow: "0 8px 24px rgba(0,0,0,0.08)", + background: + "linear-gradient(135deg, rgba(255,255,255,0.95) 0%, rgba(245,245,245,0.95) 100%)", + backdropFilter: "blur(8px)", + overflow: "hidden", + padding: 20, }} > {loading ? ( - <div style={{ textAlign: 'center', padding: 80 }}> + <div style={{ textAlign: "center", padding: 80 }}> <Spin /> </div> ) : bids.length === 0 ? ( - <div style={{ textAlign: 'center', padding: 80 }}> + <div style={{ textAlign: "center", padding: 80 }}> <Empty description="No bids found yet." /> </div> ) : ( <div className="responsive-table-wrapper"> - <Table - columns={columns(bids)} - data={bids} - rowKey="id" - pagination={{ - pageSize: 50, - sizeCanChange: true, - showTotal: true, - }} - scroll={{ x: true }} - border - style={{ transition: 'opacity 0.5s ease-in-out' }} - rowClassName={() => 'table-row-hover'} - /> + <Table + columns={columns(bids)} + data={bids} + rowKey="id" + pagination={{ + pageSize: 50, + sizeCanChange: true, + showTotal: true, + }} + scroll={{ x: true }} + border + style={{ transition: "opacity 0.5s ease-in-out" }} + rowClassName={() => "table-row-hover"} + /> </div> )} </Card> |