lfqian commited on
Commit
82ca8ff
·
1 Parent(s): dfdf49d

feat: implement Agent Arena page with Add Agent and Request Asset forms

Browse files
Files changed (1) hide show
  1. src/views/AddAssetView.vue +353 -4
src/views/AddAssetView.vue CHANGED
@@ -1,11 +1,360 @@
1
  <template>
2
- <div>
3
- <h1>Add Assets</h1>
 
4
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  </template>
6
 
7
  <script>
 
 
 
 
 
 
 
 
8
  export default {
9
- name: 'AddAssetsView'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  }
11
- </script>
 
1
  <template>
2
+ <div class="page-container">
3
+ <div class="title-container">
4
+ <span class="main-title">Agent Arena</span>
5
  </div>
6
+
7
+ <div class="cards-container">
8
+ <!-- Add Agent Card -->
9
+ <Card class="feature-card">
10
+ <template #title>
11
+ <div class="card-title">
12
+ <i class="pi pi-robot"></i>
13
+ <span>Add Trading Agent</span>
14
+ </div>
15
+ </template>
16
+ <template #content>
17
+ <div class="form-container">
18
+ <div class="field">
19
+ <label for="agentName">Agent Name</label>
20
+ <InputText
21
+ id="agentName"
22
+ v-model="agentForm.name"
23
+ placeholder="e.g., MyTradingAgent"
24
+ class="w-full"
25
+ />
26
+ </div>
27
+ <div class="field">
28
+ <label for="agentEndpoint">API Endpoint</label>
29
+ <InputText
30
+ id="agentEndpoint"
31
+ v-model="agentForm.endpoint"
32
+ placeholder="https://api.example.com/trading-agent"
33
+ class="w-full"
34
+ />
35
+ </div>
36
+ <div class="field">
37
+ <label for="agentDescription">Description (Optional)</label>
38
+ <Textarea
39
+ id="agentDescription"
40
+ v-model="agentForm.description"
41
+ placeholder="Brief description of your agent..."
42
+ rows="3"
43
+ class="w-full"
44
+ />
45
+ </div>
46
+ <Button
47
+ label="Submit Agent"
48
+ icon="pi pi-send"
49
+ @click="submitAgent"
50
+ :disabled="!agentForm.name || !agentForm.endpoint"
51
+ :loading="agentForm.loading"
52
+ class="w-full"
53
+ />
54
+ <Message v-if="agentForm.message" :severity="agentForm.messageType" :closable="false">
55
+ {{ agentForm.message }}
56
+ </Message>
57
+ </div>
58
+ </template>
59
+ </Card>
60
+
61
+ <!-- Add Asset Card -->
62
+ <Card class="feature-card">
63
+ <template #title>
64
+ <div class="card-title">
65
+ <i class="pi pi-chart-line"></i>
66
+ <span>Request Asset</span>
67
+ </div>
68
+ </template>
69
+ <template #content>
70
+ <div class="form-container">
71
+ <div class="field">
72
+ <label for="assetSymbol">Asset Symbol</label>
73
+ <InputText
74
+ id="assetSymbol"
75
+ v-model="assetForm.symbol"
76
+ placeholder="e.g., NVDA, GOOGL, SOL"
77
+ class="w-full"
78
+ />
79
+ </div>
80
+ <div class="field">
81
+ <label for="assetType">Asset Type</label>
82
+ <Dropdown
83
+ id="assetType"
84
+ v-model="assetForm.type"
85
+ :options="assetTypes"
86
+ optionLabel="label"
87
+ optionValue="value"
88
+ placeholder="Select asset type"
89
+ class="w-full"
90
+ />
91
+ </div>
92
+ <div class="field">
93
+ <label for="assetReason">Reason for Request (Optional)</label>
94
+ <Textarea
95
+ id="assetReason"
96
+ v-model="assetForm.reason"
97
+ placeholder="Why would you like to see this asset?"
98
+ rows="3"
99
+ class="w-full"
100
+ />
101
+ </div>
102
+ <Button
103
+ label="Request Asset"
104
+ icon="pi pi-plus"
105
+ @click="submitAsset"
106
+ :disabled="!assetForm.symbol || !assetForm.type"
107
+ :loading="assetForm.loading"
108
+ class="w-full"
109
+ />
110
+ <Message v-if="assetForm.message" :severity="assetForm.messageType" :closable="false">
111
+ {{ assetForm.message }}
112
+ </Message>
113
+ </div>
114
+ </template>
115
+ </Card>
116
+ </div>
117
+ </div>
118
  </template>
119
 
120
  <script>
121
+ import Card from 'primevue/card'
122
+ import InputText from 'primevue/inputtext'
123
+ import Textarea from 'primevue/textarea'
124
+ import Dropdown from 'primevue/dropdown'
125
+ import Button from 'primevue/button'
126
+ import Message from 'primevue/message'
127
+ import emailjs from 'emailjs-com'
128
+
129
  export default {
130
+ name: 'AddAssetsView',
131
+ components: {
132
+ Card,
133
+ InputText,
134
+ Textarea,
135
+ Dropdown,
136
+ Button,
137
+ Message
138
+ },
139
+ data() {
140
+ return {
141
+ agentForm: {
142
+ name: '',
143
+ endpoint: '',
144
+ description: '',
145
+ loading: false,
146
+ message: '',
147
+ messageType: 'info'
148
+ },
149
+ assetForm: {
150
+ symbol: '',
151
+ type: '',
152
+ reason: '',
153
+ loading: false,
154
+ message: '',
155
+ messageType: 'info'
156
+ },
157
+ assetTypes: [
158
+ { label: 'Stock', value: 'stock' },
159
+ { label: 'Cryptocurrency', value: 'crypto' },
160
+ { label: 'ETF', value: 'etf' },
161
+ { label: 'Other', value: 'other' }
162
+ ]
163
+ }
164
+ },
165
+ methods: {
166
+ async submitAgent() {
167
+ this.agentForm.loading = true
168
+ this.agentForm.message = ''
169
+
170
+ try {
171
+ const svc = import.meta.env.VITE_EMAILJS_SERVICE_ID
172
+ const tpl = import.meta.env.VITE_EMAILJS_TEMPLATE_ID
173
+
174
+ if (!svc || !tpl) {
175
+ this.agentForm.message = 'Email service not configured. Please contact administrator.'
176
+ this.agentForm.messageType = 'warn'
177
+ this.agentForm.loading = false
178
+ return
179
+ }
180
+
181
+ const emailData = {
182
+ title: `New Agent Submission: ${this.agentForm.name}`,
183
+ message: `Agent Name: ${this.agentForm.name}\nEndpoint: ${this.agentForm.endpoint}\nDescription: ${this.agentForm.description || 'N/A'}`
184
+ }
185
+
186
+ await emailjs.send(svc, tpl, emailData)
187
+
188
+ this.agentForm.message = 'Agent submitted successfully! We will review it soon.'
189
+ this.agentForm.messageType = 'success'
190
+
191
+ // Clear form
192
+ setTimeout(() => {
193
+ this.agentForm.name = ''
194
+ this.agentForm.endpoint = ''
195
+ this.agentForm.description = ''
196
+ this.agentForm.message = ''
197
+ }, 3000)
198
+
199
+ } catch (error) {
200
+ console.error('Error submitting agent:', error)
201
+ this.agentForm.message = 'Failed to submit agent. Please try again.'
202
+ this.agentForm.messageType = 'error'
203
+ } finally {
204
+ this.agentForm.loading = false
205
+ }
206
+ },
207
+
208
+ async submitAsset() {
209
+ this.assetForm.loading = true
210
+ this.assetForm.message = ''
211
+
212
+ try {
213
+ const svc = import.meta.env.VITE_EMAILJS_SERVICE_ID
214
+ const tpl = import.meta.env.VITE_EMAILJS_TEMPLATE_ID
215
+
216
+ if (!svc || !tpl) {
217
+ this.assetForm.message = 'Email service not configured. Please contact administrator.'
218
+ this.assetForm.messageType = 'warn'
219
+ this.assetForm.loading = false
220
+ return
221
+ }
222
+
223
+ const emailData = {
224
+ title: `New Asset Request: ${this.assetForm.symbol}`,
225
+ message: `Asset Symbol: ${this.assetForm.symbol}\nType: ${this.assetForm.type}\nReason: ${this.assetForm.reason || 'N/A'}`
226
+ }
227
+
228
+ await emailjs.send(svc, tpl, emailData)
229
+
230
+ this.assetForm.message = 'Asset request submitted successfully! We will consider adding it.'
231
+ this.assetForm.messageType = 'success'
232
+
233
+ // Clear form
234
+ setTimeout(() => {
235
+ this.assetForm.symbol = ''
236
+ this.assetForm.type = ''
237
+ this.assetForm.reason = ''
238
+ this.assetForm.message = ''
239
+ }, 3000)
240
+
241
+ } catch (error) {
242
+ console.error('Error submitting asset:', error)
243
+ this.assetForm.message = 'Failed to submit request. Please try again.'
244
+ this.assetForm.messageType = 'error'
245
+ } finally {
246
+ this.assetForm.loading = false
247
+ }
248
+ }
249
+ }
250
+ }
251
+ </script>
252
+
253
+ <style scoped>
254
+ .page-container {
255
+ max-width: 1400px;
256
+ margin: 0 auto;
257
+ padding: 1rem;
258
+ }
259
+
260
+ .title-container {
261
+ text-align: center;
262
+ margin-bottom: 2rem;
263
+ }
264
+
265
+ .main-title {
266
+ font-size: 2rem;
267
+ letter-spacing: -0.02em;
268
+ font-weight: 800;
269
+ color: #1f1f33;
270
+ }
271
+
272
+ .cards-container {
273
+ display: grid;
274
+ grid-template-columns: repeat(auto-fit, minmax(450px, 1fr));
275
+ gap: 2rem;
276
+ padding: 0 1rem;
277
+ }
278
+
279
+ .feature-card {
280
+ background: white;
281
+ border-radius: 12px;
282
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
283
+ transition: transform 0.2s, box-shadow 0.2s;
284
+ }
285
+
286
+ .feature-card:hover {
287
+ transform: translateY(-2px);
288
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
289
+ }
290
+
291
+ .card-title {
292
+ display: flex;
293
+ align-items: center;
294
+ gap: 0.75rem;
295
+ font-size: 1.25rem;
296
+ font-weight: 700;
297
+ color: #1f1f33;
298
+ }
299
+
300
+ .card-title i {
301
+ font-size: 1.5rem;
302
+ color: var(--primary-color);
303
+ }
304
+
305
+ .form-container {
306
+ display: flex;
307
+ flex-direction: column;
308
+ gap: 1.5rem;
309
+ }
310
+
311
+ .field {
312
+ display: flex;
313
+ flex-direction: column;
314
+ gap: 0.5rem;
315
+ }
316
+
317
+ .field label {
318
+ font-weight: 600;
319
+ color: #4b5563;
320
+ font-size: 0.95rem;
321
+ }
322
+
323
+ :deep(.p-inputtext),
324
+ :deep(.p-dropdown),
325
+ :deep(.p-inputtextarea) {
326
+ border-radius: 8px;
327
+ border: 1px solid #d1d5db;
328
+ padding: 0.75rem;
329
+ }
330
+
331
+ :deep(.p-inputtext:focus),
332
+ :deep(.p-dropdown:focus),
333
+ :deep(.p-inputtextarea:focus) {
334
+ border-color: var(--primary-color);
335
+ box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1);
336
+ }
337
+
338
+ :deep(.p-button) {
339
+ border-radius: 8px;
340
+ padding: 0.75rem;
341
+ font-weight: 600;
342
+ margin-top: 0.5rem;
343
+ }
344
+
345
+ :deep(.p-message) {
346
+ border-radius: 8px;
347
+ margin-top: 0.5rem;
348
+ }
349
+
350
+ @media (max-width: 768px) {
351
+ .cards-container {
352
+ grid-template-columns: 1fr;
353
+ padding: 0 0.5rem;
354
+ }
355
+
356
+ .main-title {
357
+ font-size: 1.5rem;
358
+ }
359
  }
360
+ </style>