diff options
author | Navan Chauhan <navanchauhan@gmail.com> | 2025-04-27 20:13:16 -0600 |
---|---|---|
committer | Navan Chauhan <navanchauhan@gmail.com> | 2025-04-27 20:13:16 -0600 |
commit | 6262f0789afee916340a4699ae8f2b6a2e93e4ac (patch) | |
tree | 66d00cb5cf9b9f4516ac8602f262cda2bc906768 /client | |
parent | 04db14b907bdc708fd5607d381e011505c61d808 (diff) |
create submit bid page
Diffstat (limited to 'client')
-rw-r--r-- | client/src/SubmitBidPage.jsx | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/client/src/SubmitBidPage.jsx b/client/src/SubmitBidPage.jsx new file mode 100644 index 0000000..65a9eb8 --- /dev/null +++ b/client/src/SubmitBidPage.jsx @@ -0,0 +1,146 @@ +import React, { useState, useEffect } from 'react'; +import { Form, InputNumber, DatePicker, Button, Message, Typography, Card } from '@arco-design/web-react'; +import '@arco-design/web-react/dist/css/arco.css'; +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import timezone from 'dayjs/plugin/timezone'; +import API_BASE_URL from './config'; + +dayjs.extend(utc); +dayjs.extend(timezone); + +function SubmitBidPage() { + const [form] = Form.useForm(); + const [loading, setLoading] = useState(false); + const [localNow, setLocalNow] = useState(''); + const [newEnglandNow, setNewEnglandNow] = useState(''); + + useEffect(() => { + const updateTime = () => { + const now = dayjs(); + const localFormatted = now.format('dddd, MMMM D, h:mm A'); + + const newEngland = now.tz('America/New_York'); + const newEnglandFormatted = newEngland.format('dddd, MMMM D, h:mm A'); + + setLocalNow(localFormatted); + setNewEnglandNow(newEnglandFormatted); + }; + + updateTime(); + const interval = setInterval(updateTime, 1000); // update every second + + return () => clearInterval(interval); + }, []); + + const handleSubmit = async (values) => { + setLoading(true); + try { + const picked = dayjs(values.timestamp); + const adjusted = picked.minute(0).second(0).millisecond(0); + + const payload = { + timestamp: adjusted.tz('America/New_York').format(), + quantity: values.quantity, + price: values.price, + user_id: 1 // Hardcoded user id for now + }; + + const res = await fetch(`${API_BASE_URL}/bids/`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }); + + if (!res.ok) { + const error = await res.json(); + throw new Error(error.detail || 'Failed to submit bid'); + } + + Message.success('Bid submitted successfully!'); + form.resetFields(); + } catch (err) { + console.error(err); + Message.error(err.message || 'Submission failed'); + } finally { + setLoading(false); + } + }; + + return ( + <div style={{ padding: 20, backgroundColor: 'var(--color-fill-2)' }}> + <Typography.Title heading={4}>Submit New Bid</Typography.Title> + <Card style={{ marginTop: 16 }}> + {/* 🕰️ Show Current Time Info */} + <Typography.Paragraph> + <strong>Current Local Time:</strong> {localNow} + </Typography.Paragraph> + <Typography.Paragraph> + <strong>Current New England Time:</strong> {newEnglandNow} + </Typography.Paragraph> + + <Form + form={form} + layout="vertical" + onSubmit={handleSubmit} + initialValues={{ + quantity: 0, + price: 0 + }} + > + <Form.Item + label="Bid Date and Hour" + field="timestamp" + rules={[{ required: true, message: 'Please select bid date and hour' }]} + > + <DatePicker + showTime={{ + format: 'h A', + defaultValue: dayjs().hour(0).minute(0), + disabledMinutes: () => Array.from({ length: 60 }, (_, i) => i !== 0), + step: { minute: 60 } + }} + style={{ width: '100%' }} + format="YYYY-MM-DD HH:00" + placeholder="Select date and hour" + timezone='America/New_York' + disabledMinutes={() => Array.from({ length: 60 }, (_, i) => i !== 0)} + /> + </Form.Item> + + <Form.Item + label="Quantity (MW)" + field="quantity" + rules={[ + { required: true, message: 'Please enter quantity' }, + { type: 'number', min: 0.01, message: 'Quantity must be > 0' } + ]} + > + <InputNumber style={{ width: '100%' }} placeholder="Enter quantity" /> + </Form.Item> + + <Form.Item + label="Price ($/MWh)" + field="price" + rules={[ + { required: true, message: 'Please enter price' }, + { type: 'number', min: 0, message: 'Price must be >= 0' } + ]} + > + <InputNumber style={{ width: '100%' }} placeholder="Enter price" /> + </Form.Item> + + <Form.Item> + <Button type="primary" htmlType="submit" loading={loading}> + Submit Bid + </Button> + </Form.Item> + </Form> + </Card> + </div> + ); +} + +export default SubmitBidPage; |