Skip to content

Commit 599f830

Browse files
committed
Update AddStockModal with full functionality
1 parent 6d08902 commit 599f830

File tree

1 file changed

+168
-43
lines changed

1 file changed

+168
-43
lines changed

src/components/modals/AddStockModal.jsx

Lines changed: 168 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,74 @@
1-
import { Fragment } from 'react';
1+
import { Fragment, useState } from 'react';
22
import { Dialog, Transition } from '@headlessui/react';
33
import { XMarkIcon } from '@heroicons/react/24/outline';
44
import { TextInput, NumberInput, Button } from '@tremor/react';
5+
import axios from 'axios';
6+
7+
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL;
8+
9+
export default function AddStockModal({ open, setOpen, onStockAdded }) {
10+
const [loading, setLoading] = useState(false);
11+
const [error, setError] = useState('');
12+
const [formData, setFormData] = useState({
13+
name: '',
14+
ticker: '',
15+
shares: '',
16+
buy_price: '',
17+
target_price: ''
18+
});
19+
20+
const handleChange = (e) => {
21+
const { name, value } = e.target;
22+
setFormData(prev => ({
23+
...prev,
24+
[name]: value
25+
}));
26+
setError(''); // Clear error when user makes changes
27+
};
28+
29+
const handleSubmit = async (e) => {
30+
e.preventDefault();
31+
setLoading(true);
32+
setError('');
33+
34+
try {
35+
// Validate form data
36+
if (!formData.name || !formData.ticker || !formData.shares || !formData.buy_price) {
37+
throw new Error('Please fill in all required fields');
38+
}
39+
40+
const response = await axios.post(`${API_BASE_URL}/stocks`, {
41+
name: formData.name,
42+
ticker: formData.ticker.toUpperCase(),
43+
shares: parseFloat(formData.shares),
44+
buy_price: parseFloat(formData.buy_price),
45+
target_price: parseFloat(formData.target_price || formData.buy_price)
46+
});
47+
48+
console.log('Stock added successfully:', response.data);
49+
50+
// Reset form and close modal
51+
setFormData({
52+
name: '',
53+
ticker: '',
54+
shares: '',
55+
buy_price: '',
56+
target_price: ''
57+
});
58+
setOpen(false);
59+
60+
// Notify parent component
61+
if (onStockAdded) {
62+
onStockAdded(response.data);
63+
}
64+
} catch (error) {
65+
console.error('Error adding stock:', error);
66+
setError(error.response?.data?.error || error.message || 'Failed to add stock');
67+
} finally {
68+
setLoading(false);
69+
}
70+
};
571

6-
export default function AddStockModal({ open, setOpen }) {
772
return (
873
<Transition.Root show={open} as={Fragment}>
974
<Dialog as="div" className="relative z-50" onClose={setOpen}>
@@ -41,50 +106,110 @@ export default function AddStockModal({ open, setOpen }) {
41106
<XMarkIcon className="h-6 w-6" aria-hidden="true" />
42107
</button>
43108
</div>
44-
<div className="sm:flex sm:items-start">
45-
<div className="mt-3 text-center sm:mt-0 sm:text-left w-full">
46-
<Dialog.Title as="h3" className="text-lg font-semibold leading-6 text-gray-900">
47-
Add Stock to Watchlist
48-
</Dialog.Title>
49-
<div className="mt-6 space-y-4">
50-
<div>
51-
<label htmlFor="symbol" className="block text-sm font-medium text-gray-700">
52-
Stock Symbol
53-
</label>
54-
<TextInput
55-
id="symbol"
56-
placeholder="Enter stock symbol (e.g., AAPL)"
57-
className="mt-1"
58-
/>
59-
</div>
60-
<div>
61-
<label htmlFor="alertPrice" className="block text-sm font-medium text-gray-700">
62-
Alert Price
63-
</label>
64-
<NumberInput
65-
id="alertPrice"
66-
placeholder="Enter alert price"
67-
className="mt-1"
68-
/>
109+
<form onSubmit={handleSubmit}>
110+
<div className="sm:flex sm:items-start">
111+
<div className="mt-3 text-center sm:mt-0 sm:text-left w-full">
112+
<Dialog.Title as="h3" className="text-lg font-semibold leading-6 text-gray-900">
113+
Add Stock
114+
</Dialog.Title>
115+
{error && (
116+
<div className="mt-2 text-sm text-red-600">
117+
{error}
118+
</div>
119+
)}
120+
<div className="mt-6 space-y-4">
121+
<div>
122+
<label htmlFor="name" className="block text-sm font-medium text-gray-700">
123+
Company Name
124+
</label>
125+
<TextInput
126+
id="name"
127+
name="name"
128+
value={formData.name}
129+
onChange={handleChange}
130+
placeholder="Enter company name"
131+
className="mt-1"
132+
required
133+
/>
134+
</div>
135+
<div>
136+
<label htmlFor="ticker" className="block text-sm font-medium text-gray-700">
137+
Stock Symbol
138+
</label>
139+
<TextInput
140+
id="ticker"
141+
name="ticker"
142+
value={formData.ticker}
143+
onChange={handleChange}
144+
placeholder="Enter stock symbol (e.g., AAPL)"
145+
className="mt-1"
146+
required
147+
/>
148+
</div>
149+
<div>
150+
<label htmlFor="shares" className="block text-sm font-medium text-gray-700">
151+
Number of Shares
152+
</label>
153+
<NumberInput
154+
id="shares"
155+
name="shares"
156+
value={formData.shares}
157+
onChange={handleChange}
158+
placeholder="Enter number of shares"
159+
className="mt-1"
160+
required
161+
/>
162+
</div>
163+
<div>
164+
<label htmlFor="buy_price" className="block text-sm font-medium text-gray-700">
165+
Buy Price
166+
</label>
167+
<NumberInput
168+
id="buy_price"
169+
name="buy_price"
170+
value={formData.buy_price}
171+
onChange={handleChange}
172+
placeholder="Enter buy price"
173+
className="mt-1"
174+
required
175+
/>
176+
</div>
177+
<div>
178+
<label htmlFor="target_price" className="block text-sm font-medium text-gray-700">
179+
Target Price (Optional)
180+
</label>
181+
<NumberInput
182+
id="target_price"
183+
name="target_price"
184+
value={formData.target_price}
185+
onChange={handleChange}
186+
placeholder="Enter target price"
187+
className="mt-1"
188+
/>
189+
</div>
69190
</div>
70191
</div>
71192
</div>
72-
</div>
73-
<div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
74-
<Button
75-
variant="primary"
76-
className="w-full sm:w-auto sm:ml-3"
77-
>
78-
Add to Watchlist
79-
</Button>
80-
<Button
81-
variant="secondary"
82-
className="mt-3 w-full sm:mt-0 sm:w-auto"
83-
onClick={() => setOpen(false)}
84-
>
85-
Cancel
86-
</Button>
87-
</div>
193+
<div className="mt-5 sm:mt-4 sm:flex sm:flex-row-reverse">
194+
<Button
195+
type="submit"
196+
variant="primary"
197+
className="w-full sm:w-auto sm:ml-3"
198+
disabled={loading}
199+
>
200+
{loading ? 'Adding...' : 'Add Stock'}
201+
</Button>
202+
<Button
203+
type="button"
204+
variant="secondary"
205+
className="mt-3 w-full sm:mt-0 sm:w-auto"
206+
onClick={() => setOpen(false)}
207+
disabled={loading}
208+
>
209+
Cancel
210+
</Button>
211+
</div>
212+
</form>
88213
</Dialog.Panel>
89214
</Transition.Child>
90215
</div>

0 commit comments

Comments
 (0)