aboutsummaryrefslogtreecommitdiff
path: root/client/src/SubmitBidPage.jsx
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/SubmitBidPage.jsx')
-rw-r--r--client/src/SubmitBidPage.jsx146
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;