jomasego commited on
Commit
5df66b9
·
verified ·
1 Parent(s): 9750e28

Upload templates/index.html with huggingface_hub

Browse files
Files changed (1) hide show
  1. templates/index.html +741 -0
templates/index.html ADDED
@@ -0,0 +1,741 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <title>International Trade Flow Predictor</title>
6
+ <link rel="stylesheet" href="/static/css/style.css">
7
+ <!-- Font Awesome for icons -->
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
9
+ <!-- Leaflet for maps -->
10
+ <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
11
+ <style>
12
+ .advanced-chart-container {
13
+ width: 100%;
14
+ height: 400px;
15
+ margin-top: 1.5em;
16
+ position: relative;
17
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
18
+ border-radius: 8px;
19
+ overflow: hidden;
20
+ }
21
+ .treemap-container {
22
+ width: 100%;
23
+ border: 1px solid #eaeaea;
24
+ border-radius: 8px;
25
+ }
26
+ .treemap-title {
27
+ font-weight: bold;
28
+ padding: 10px;
29
+ background: #f8f9fa;
30
+ border-bottom: 1px solid #eaeaea;
31
+ }
32
+ .treemap-item:hover {
33
+ opacity: 0.9;
34
+ transform: scale(1.02);
35
+ transition: all 0.2s ease;
36
+ z-index: 5;
37
+ }
38
+ .chart-controls {
39
+ display: flex;
40
+ flex-wrap: wrap;
41
+ gap: 10px;
42
+ margin: 1em 0;
43
+ }
44
+ .chart-type-btn {
45
+ padding: 6px 12px;
46
+ background: #f0f4f8;
47
+ border: 1px solid #ddd;
48
+ border-radius: 4px;
49
+ cursor: pointer;
50
+ transition: all 0.2s;
51
+ }
52
+ .chart-type-btn:hover {
53
+ background: #e3e9f6;
54
+ }
55
+ .chart-type-btn.active {
56
+ background: #1976d2;
57
+ color: white;
58
+ border-color: #1976d2;
59
+ }
60
+ .cached-data-panel {
61
+ margin-top: 2em;
62
+ border: 1px solid #eaeaea;
63
+ border-radius: 8px;
64
+ overflow: hidden;
65
+ }
66
+ .cached-data-header {
67
+ padding: 10px 15px;
68
+ background: #f8f9fa;
69
+ font-weight: bold;
70
+ border-bottom: 1px solid #eaeaea;
71
+ display: flex;
72
+ justify-content: space-between;
73
+ align-items: center;
74
+ }
75
+ .cached-data-list {
76
+ max-height: 300px;
77
+ overflow-y: auto;
78
+ padding: 0;
79
+ }
80
+ .cached-data-item {
81
+ padding: 8px 15px;
82
+ border-bottom: 1px solid #eee;
83
+ display: flex;
84
+ justify-content: space-between;
85
+ align-items: center;
86
+ }
87
+ .cached-data-item:hover {
88
+ background: #f9f9fa;
89
+ }
90
+ .cached-data-actions {
91
+ display: flex;
92
+ gap: 5px;
93
+ }
94
+ .cached-data-info {
95
+ font-size: 13px;
96
+ color: #666;
97
+ }
98
+ .action-btn {
99
+ background: none;
100
+ border: none;
101
+ color: #1976d2;
102
+ cursor: pointer;
103
+ padding: 3px 8px;
104
+ border-radius: 3px;
105
+ }
106
+ .action-btn:hover {
107
+ background: #e3e9f6;
108
+ }
109
+ .action-btn.delete {
110
+ color: #e53935;
111
+ }
112
+ .action-btn.delete:hover {
113
+ background: #ffebee;
114
+ }
115
+
116
+ /* AI Assistant styles */
117
+ .chat-container {
118
+ display: flex;
119
+ flex-direction: column;
120
+ height: 500px;
121
+ border: 1px solid #e0e0e0;
122
+ border-radius: 8px;
123
+ overflow: hidden;
124
+ }
125
+
126
+ .chat-messages {
127
+ flex: 1;
128
+ overflow-y: auto;
129
+ padding: 15px;
130
+ background: #f9f9fa;
131
+ }
132
+
133
+ .chat-input-container {
134
+ display: flex;
135
+ border-top: 1px solid #e0e0e0;
136
+ padding: 10px;
137
+ background: #fff;
138
+ }
139
+
140
+ .chat-input {
141
+ flex: 1;
142
+ padding: 10px;
143
+ border: 1px solid #ddd;
144
+ border-radius: 20px;
145
+ margin-right: 10px;
146
+ }
147
+
148
+ .chat-send-btn {
149
+ background: #1976d2;
150
+ color: white;
151
+ border: none;
152
+ border-radius: 20px;
153
+ padding: 10px 20px;
154
+ cursor: pointer;
155
+ }
156
+
157
+ .message {
158
+ margin-bottom: 15px;
159
+ max-width: 80%;
160
+ }
161
+
162
+ .message-user {
163
+ align-self: flex-end;
164
+ margin-left: auto;
165
+ background: #e3f2fd;
166
+ border-radius: 18px 18px 0 18px;
167
+ padding: 10px 15px;
168
+ }
169
+
170
+ .message-assistant {
171
+ align-self: flex-start;
172
+ background: #fff;
173
+ border-radius: 18px 18px 18px 0;
174
+ padding: 10px 15px;
175
+ border: 1px solid #e0e0e0;
176
+ }
177
+
178
+ .message-loading {
179
+ display: flex;
180
+ align-items: center;
181
+ padding: 10px 15px;
182
+ }
183
+
184
+ .loading-dots span {
185
+ display: inline-block;
186
+ width: 8px;
187
+ height: 8px;
188
+ border-radius: 50%;
189
+ background-color: #1976d2;
190
+ margin-right: 3px;
191
+ animation: loading-bounce 1.4s infinite ease-in-out both;
192
+ }
193
+
194
+ .loading-dots span:nth-child(1) { animation-delay: -0.32s; }
195
+ .loading-dots span:nth-child(2) { animation-delay: -0.16s; }
196
+
197
+ @keyframes loading-bounce {
198
+ 0%, 80%, 100% { transform: scale(0); }
199
+ 40% { transform: scale(1); }
200
+ }
201
+
202
+ .quick-questions {
203
+ display: flex;
204
+ flex-wrap: wrap;
205
+ gap: 8px;
206
+ margin-top: 10px;
207
+ }
208
+
209
+ .quick-question-btn {
210
+ background: #f0f4f8;
211
+ border: 1px solid #ddd;
212
+ border-radius: 16px;
213
+ padding: 6px 12px;
214
+ font-size: 13px;
215
+ cursor: pointer;
216
+ transition: all 0.2s;
217
+ }
218
+
219
+ .quick-question-btn:hover {
220
+ background: #e3e9f6;
221
+ }
222
+
223
+ .badge {
224
+ display: inline-block;
225
+ padding: 2px 6px;
226
+ border-radius: 10px;
227
+ background-color: #E53935;
228
+ color: white;
229
+ font-size: 10px;
230
+ font-weight: bold;
231
+ margin-left: 5px;
232
+ vertical-align: top;
233
+ }
234
+ </style>
235
+ </head>
236
+ <body>
237
+ <!-- Banner for sources and rate-limit info -->
238
+ <div id="info-banner" style="background:#f8f9fa;border-bottom:1px solid #e0e0e0;padding:6px 16px;font-size:13px;display:flex;justify-content:space-between;align-items:center;">
239
+ <div>Sources: UN COMTRADE, WTO, World Bank. Limit: 1 request/sec, 100 requests/hour.</div>
240
+ <div style="display:flex;align-items:center;gap:8px;">
241
+ <span style="font-weight:500;">Powered by</span>
242
+ <a href="https://huggingface.co" target="_blank" style="display:flex;align-items:center;">
243
+ <img src="https://huggingface.co/front/assets/huggingface_logo.svg" alt="Hugging Face" style="height:20px;">
244
+ </a>
245
+ </div>
246
+ </div>
247
+ <!-- Tab Navigation -->
248
+ <nav>
249
+ <ul id="main-tabs" class="tab-bar">
250
+ <li class="tab active" data-tab="basics" tabindex="0" aria-selected="true">Basics</li>
251
+ <li class="tab" data-tab="exports-country" tabindex="0" aria-selected="false">Exports by Country</li>
252
+ <li class="tab" data-tab="imports-country" tabindex="0" aria-selected="false">Imports by Country</li>
253
+ <li class="tab" data-tab="exports-product" tabindex="0" aria-selected="false">Exports by Product</li>
254
+ <li class="tab" data-tab="imports-product" tabindex="0" aria-selected="false">Imports by Product</li>
255
+ <li class="tab" data-tab="rankings" tabindex="0" aria-selected="false">Rankings</li>
256
+ <li class="tab" data-tab="bilateral" tabindex="0" aria-selected="false">Bilateral Trade</li>
257
+ <li class="tab" data-tab="data-download" tabindex="0" aria-selected="false">Data Download</li>
258
+ <li class="tab" data-tab="prediction" tabindex="0" aria-selected="false">Prediction (ML)</li>
259
+ <li class="tab" data-tab="data-cache" tabindex="0" aria-selected="false">Data Cache</li>
260
+ <li class="tab" data-tab="assistant" tabindex="0" aria-selected="false">AI Assistant <span class="badge">New</span></li>
261
+ </ul>
262
+ </nav>
263
+ <style>
264
+ .tab-bar {
265
+ display: flex;
266
+ list-style: none;
267
+ padding: 0;
268
+ margin: 0 0 16px 0;
269
+ border-bottom: 2px solid #e4e4e4;
270
+ background: #f9f9fa;
271
+ }
272
+ .tab-bar .tab {
273
+ padding: 12px 28px 10px 28px;
274
+ margin: 0 2px;
275
+ border: none;
276
+ background: none;
277
+ font-size: 16px;
278
+ color: #444;
279
+ cursor: pointer;
280
+ border-radius: 8px 8px 0 0;
281
+ transition: background 0.18s, color 0.18s;
282
+ outline: none;
283
+ position: relative;
284
+ }
285
+ .tab-bar .tab.active,
286
+ .tab-bar .tab:focus {
287
+ background: #fff;
288
+ color: #1976d2;
289
+ box-shadow: 0 -2px 8px rgba(25,118,210,0.07);
290
+ border-bottom: 2px solid #1976d2;
291
+ z-index: 2;
292
+ }
293
+ .tab-bar .tab:hover:not(.active) {
294
+ background: #e3e9f6;
295
+ color: #1976d2;
296
+ }
297
+ </style>
298
+ <!-- Tab Content Panels -->
299
+ <div id="tab-content-basics" class="tab-content" style="display:block;">
300
+ <div class="container">
301
+ <h1>International Trade Flow Predictor</h1>
302
+ <div id="alert" class="alert" style="display:none;"></div>
303
+ <form id="tradeForm">
304
+ <label for="reporterCode">Reporter Country:</label>
305
+ <select id="reporterCode" name="reporterCode"></select>
306
+ <label for="partnerCode">Partner Country:</label>
307
+ <select id="partnerCode" name="partnerCode"></select>
308
+ <label for="period">Year:</label>
309
+ <input type="text" id="period" name="period" value="2022" placeholder="e.g. 2022" title="Year (e.g. 2022)">
310
+ <label for="cmdCode">Commodity Code (HS or TOTAL):</label>
311
+ <input type="text" id="cmdCode" name="cmdCode" value="TOTAL" placeholder="e.g. TOTAL or 1001" title="HS code or TOTAL for all commodities">
312
+ <label for="flowCode">Flow (M=Import, X=Export, blank=All):</label>
313
+ <input type="text" id="flowCode" name="flowCode" placeholder="M, X or leave blank" title="M = Import, X = Export, blank = All">
314
+ <button type="submit">Fetch Trade Data</button>
315
+ </form>
316
+ <div id="spinner" class="spinner" style="display:none;"></div>
317
+ <div id="results"></div>
318
+ <canvas id="tradeChart" style="margin-top:2em;max-width:100%;display:none;"></canvas>
319
+
320
+ </div>
321
+ <!-- Select2 for searchable dropdowns -->
322
+
323
+
324
+ <!-- JavaScript modules -->
325
+ <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
326
+ <script src="/static/js/country_codes.js"></script>
327
+ <script src="/static/js/data_manager.js"></script>
328
+ <script src="/static/js/charts_module.js"></script>
329
+ <script src="/static/js/main.js"></script>
330
+ <script src="/static/js/enhanced_visualizations.js"></script>
331
+ <script src="/static/js/assistant.js"></script>
332
+ <div id="worldMap" style="width:100%;height:360px;margin-top:2em;"></div>
333
+ <div id="extraVisualizations" style="margin-top:2em;"></div>
334
+ <script>
335
+ // Populate country dropdowns from COUNTRY_CODES
336
+ document.addEventListener('DOMContentLoaded', function() {
337
+ function populateCountrySelect(selectId, defaultCode) {
338
+ const select = document.getElementById(selectId);
339
+ if (!select || typeof COUNTRY_CODES === 'undefined') return;
340
+ select.innerHTML = '';
341
+ COUNTRY_CODES.forEach(c => {
342
+ const opt = document.createElement('option');
343
+ opt.value = c.code;
344
+ opt.textContent = c.name + ' (' + c.code + ')';
345
+ if (c.code === defaultCode) opt.selected = true;
346
+ select.appendChild(opt);
347
+ });
348
+ // Make dropdown searchable with Select2
349
+ window.$ && window.$(select).select2 && window.$(select).select2();
350
+ }
351
+ populateCountrySelect('reporterCode', '842');
352
+ populateCountrySelect('partnerCode', '156');
353
+ });
354
+ </script>
355
+ <!-- jQuery for select2 -->
356
+ <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
357
+ </div>
358
+ <div id="tab-content-exports-country" class="tab-content" style="display:none;">
359
+ <h3>Exports by Country</h3>
360
+ <form id="exportsCountryForm" style="margin-bottom:1em;">
361
+ <label for="exportsCountryYear">Year:</label>
362
+ <input type="number" id="exportsCountryYear" name="exportsCountryYear" value="2022" min="2000" max="2100" style="width:90px;">
363
+ <label for="exportsCountryCommodity">Commodity Code (HS or TOTAL):</label>
364
+ <input type="text" id="exportsCountryCommodity" name="exportsCountryCommodity" value="TOTAL" style="width:110px;">
365
+ <label for="exportsCountryFlow">Flow:</label>
366
+ <select id="exportsCountryFlow" name="exportsCountryFlow">
367
+ <option value="X">Export</option>
368
+ <option value="M">Import</option>
369
+ <option value="">All</option>
370
+ </select>
371
+ <button type="submit">Show Table</button>
372
+ </form>
373
+ <button id="exportsCountryDownloadBtn" style="display:none;margin-bottom:1em;">Download CSV</button>
374
+ <div id="exportsCountryResults"></div>
375
+ <div id="exportsCountryChart" style="margin-top:2em;"></div>
376
+ </div>
377
+ <div id="tab-content-imports-country" class="tab-content" style="display:none;">
378
+ <h3>Imports by Country</h3>
379
+ <form id="importsCountryForm" style="margin-bottom:1em;">
380
+ <label for="importsCountryYear">Year:</label>
381
+ <input type="number" id="importsCountryYear" name="importsCountryYear" value="2022" min="2000" max="2100" style="width:90px;">
382
+ <label for="importsCountryCommodity">Commodity Code (HS or TOTAL):</label>
383
+ <input type="text" id="importsCountryCommodity" name="importsCountryCommodity" value="TOTAL" style="width:110px;">
384
+ <label for="importsCountryFlow">Flow:</label>
385
+ <select id="importsCountryFlow" name="importsCountryFlow">
386
+ <option value="M">Import</option>
387
+ <option value="X">Export</option>
388
+ <option value="">All</option>
389
+ </select>
390
+ <button type="submit">Show Table</button>
391
+ </form>
392
+ <button id="importsCountryDownloadBtn" style="display:none;margin-bottom:1em;">Download CSV</button>
393
+ <div id="importsCountryResults"></div>
394
+ <div id="importsCountryChart" style="margin-top:2em;"></div>
395
+ </div>
396
+ <div id="tab-content-exports-product" class="tab-content" style="display:none;">
397
+ <h3>Exports by Product</h3>
398
+ <form id="exportsProductForm" style="margin-bottom:1em;">
399
+ <label for="exportsProductCountry">Country:</label>
400
+ <select id="exportsProductCountry" name="exportsProductCountry"></select>
401
+ <label for="exportsProductYear">Year:</label>
402
+ <input type="number" id="exportsProductYear" name="exportsProductYear" value="2022" min="2000" max="2100" style="width:90px;">
403
+ <button type="submit">Show Table</button>
404
+ </form>
405
+ <button id="exportsProductDownloadBtn" style="display:none;margin-bottom:1em;">Download CSV</button>
406
+ <div id="exportsProductResults"></div>
407
+ <div id="exportsProductChart" style="margin-top:2em;"></div>
408
+ </div>
409
+ <div id="tab-content-imports-product" class="tab-content" style="display:none;">
410
+ <h3>Imports by Product</h3>
411
+ <form id="importsProductForm" style="margin-bottom:1em;">
412
+ <label for="importsProductCountry">Country:</label>
413
+ <select id="importsProductCountry" name="importsProductCountry"></select>
414
+ <label for="importsProductYear">Year:</label>
415
+ <input type="number" id="importsProductYear" name="importsProductYear" value="2022" min="2000" max="2100" style="width:90px;">
416
+ <button type="submit">Show Table</button>
417
+ </form>
418
+ <button id="importsProductDownloadBtn" style="display:none;margin-bottom:1em;">Download CSV</button>
419
+ <div id="importsProductResults"></div>
420
+ <div id="importsProductChart" style="margin-top:2em;"></div>
421
+ </div>
422
+ <div id="tab-content-rankings" class="tab-content" style="display:none;">
423
+ <h3>Ranking of Countries</h3>
424
+ <form id="rankingsForm" style="margin-bottom:1em;">
425
+ <label for="rankingsYear">Year:</label>
426
+ <input type="number" id="rankingsYear" name="rankingsYear" value="2022" min="2000" max="2100" style="width:90px;">
427
+ <label for="rankingsCommodity">Commodity Code (HS or TOTAL):</label>
428
+ <input type="text" id="rankingsCommodity" name="rankingsCommodity" value="TOTAL" style="width:110px;">
429
+ <label for="rankingsFlow">Flow:</label>
430
+ <select id="rankingsFlow" name="rankingsFlow">
431
+ <option value="X">Exporters</option>
432
+ <option value="M">Importers</option>
433
+ </select>
434
+ <button type="submit">Show Rankings</button>
435
+ </form>
436
+ <button id="rankingsDownloadBtn" style="display:none;margin-bottom:1em;">Download CSV</button>
437
+ <div id="rankingsResults"></div>
438
+ <div id="rankingsChart" style="margin-top:2em;"></div>
439
+ </div>
440
+ <div id="tab-content-bilateral" class="tab-content" style="display:none;">
441
+ <h3>Bilateral Trade</h3>
442
+ <form id="bilateralForm" style="margin-bottom:1em;">
443
+ <label for="bilateralReporter">Reporter Country:</label>
444
+ <select id="bilateralReporter" name="bilateralReporter"></select>
445
+ <label for="bilateralPartner">Partner Country:</label>
446
+ <select id="bilateralPartner" name="bilateralPartner"></select>
447
+ <label for="bilateralYear">Year:</label>
448
+ <input type="number" id="bilateralYear" name="bilateralYear" value="2022" min="2000" max="2100" style="width:90px;">
449
+ <label for="bilateralCommodity">Commodity Code (HS or TOTAL):</label>
450
+ <input type="text" id="bilateralCommodity" name="bilateralCommodity" value="TOTAL" style="width:110px;">
451
+ <button type="submit">Show Trade</button>
452
+ </form>
453
+ <button id="bilateralDownloadBtn" style="display:none;margin-bottom:1em;">Download CSV</button>
454
+ <div id="bilateralResults"></div>
455
+ <div id="bilateralChart" style="margin-top:2em;"></div>
456
+ </div>
457
+ <div id="tab-content-data-download" class="tab-content" style="display:none;">
458
+ <h3>Data Download</h3>
459
+ <form id="dataDownloadForm" style="margin-bottom:1em;">
460
+ <label for="dataDownloadReporter">Reporter Country:</label>
461
+ <select id="dataDownloadReporter" name="dataDownloadReporter">
462
+ <option value="">All</option>
463
+ </select>
464
+ <label for="dataDownloadPartner">Partner Country:</label>
465
+ <select id="dataDownloadPartner" name="dataDownloadPartner">
466
+ <option value="">All</option>
467
+ </select>
468
+ <label for="dataDownloadYear">Year:</label>
469
+ <input type="number" id="dataDownloadYear" name="dataDownloadYear" min="2000" max="2100" style="width:90px;">
470
+ <label for="dataDownloadCommodity">Commodity Code (HS or TOTAL):</label>
471
+ <input type="text" id="dataDownloadCommodity" name="dataDownloadCommodity" style="width:110px;">
472
+ <label for="dataDownloadFlow">Flow:</label>
473
+ <select id="dataDownloadFlow" name="dataDownloadFlow">
474
+ <option value="">All</option>
475
+ <option value="X">Export</option>
476
+ <option value="M">Import</option>
477
+ </select>
478
+ <button type="submit">Download CSV</button>
479
+ </form>
480
+ <div id="dataDownloadStatus"></div>
481
+ </div>
482
+ <div id="tab-content-prediction" class="tab-content" style="display:none;">
483
+ <h3>Trade Flow Prediction (ML)</h3>
484
+ <form id="predictionForm" style="margin-bottom:1em;">
485
+ <label for="predictionReporter">Reporter Country:</label>
486
+ <select id="predictionReporter" name="predictionReporter"></select>
487
+ <label for="predictionPartner">Partner Country:</label>
488
+ <select id="predictionPartner" name="predictionPartner"></select>
489
+ <label for="predictionYear">Year to Predict:</label>
490
+ <input type="number" id="predictionYear" name="predictionYear" value="2023" min="2000" max="2100" style="width:90px;">
491
+ <label for="predictionCommodity">Commodity Code (HS or TOTAL):</label>
492
+ <input type="text" id="predictionCommodity" name="predictionCommodity" value="TOTAL" style="width:110px;">
493
+ <label for="predictionModel">Model:</label>
494
+ <select id="predictionModel" name="predictionModel">
495
+ <option value="linear">Linear Regression</option>
496
+ <option value="xgboost">XGBoost</option>
497
+ <option value="lstm">LSTM</option>
498
+ </select>
499
+ <button type="submit">Predict</button>
500
+ </form>
501
+ <button id="predictionDownloadBtn" style="display:none;margin-bottom:1em;">Download CSV</button>
502
+ <div id="predictionResults"></div>
503
+ <div id="predictionChart" style="margin-top:2em;"></div>
504
+ </div>
505
+
506
+ <!-- Data Cache Management Panel -->
507
+ <div id="tab-content-data-cache" class="tab-content" style="display:none;">
508
+ <div class="container">
509
+ <h3>Data Cache Management</h3>
510
+ <p>View, use, and manage previously cached trade data to reduce API calls and work offline.</p>
511
+
512
+ <div class="cached-data-panel">
513
+ <div class="cached-data-header">
514
+ <span>Cached Datasets</span>
515
+ <div>
516
+ <button id="refreshCacheBtn" class="action-btn"><i class="fas fa-sync-alt"></i> Refresh</button>
517
+ <button id="clearAllCacheBtn" class="action-btn delete"><i class="fas fa-trash"></i> Clear All</button>
518
+ </div>
519
+ </div>
520
+ <div id="cachedDataList" class="cached-data-list">
521
+ <!-- Cache items will be populated here -->
522
+ <div class="cached-data-item" style="text-align:center;padding:20px;color:#666;">
523
+ <i class="fas fa-spinner fa-spin"></i> Loading cached data...
524
+ </div>
525
+ </div>
526
+ </div>
527
+
528
+ <div class="chart-controls">
529
+ <h4>Visualization Options:</h4>
530
+ <button class="chart-type-btn" data-type="bar"><i class="fas fa-chart-bar"></i> Bar Chart</button>
531
+ <button class="chart-type-btn" data-type="pie"><i class="fas fa-chart-pie"></i> Pie Chart</button>
532
+ <button class="chart-type-btn" data-type="line"><i class="fas fa-chart-line"></i> Line Chart</button>
533
+ <button class="chart-type-btn" data-type="treemap"><i class="fas fa-th-large"></i> Treemap</button>
534
+ <button class="chart-type-btn" data-type="map"><i class="fas fa-globe"></i> World Map</button>
535
+ </div>
536
+
537
+ <div id="cacheVisualization" class="advanced-chart-container" style="display:none;">
538
+ <!-- Visualizations will be rendered here -->
539
+ </div>
540
+ </div>
541
+ </div>
542
+
543
+ <div id="tab-content-assistant" class="tab-content" style="display:none;">
544
+ <div class="container">
545
+ <h3>AI Trade Assistant <span style="font-size:14px;color:#666;font-weight:normal;display:flex;align-items:center;gap:6px;">
546
+ (Powered by Google Gemma-2b on
547
+ <a href="https://huggingface.co/google/gemma-2b-it" target="_blank" style="display:flex;align-items:center;text-decoration:none;">
548
+ <img src="https://huggingface.co/front/assets/huggingface_logo.svg" alt="Hugging Face" style="height:18px;margin-right:3px;"> Hugging Face
549
+ </a>)
550
+ </span></h3>
551
+
552
+ <div class="chat-container" style="border: 1px solid #dee2e6; border-radius: 8px; height: 500px; display: flex; flex-direction: column; overflow: hidden;">
553
+ <div id="chat-messages" class="chat-messages" style="flex: 1; overflow-y: auto; padding: 20px; background-color: #f8f9fa;">
554
+ <!-- Welcome message -->
555
+ <div class="message message-assistant" style="background-color: white; border-radius: 10px; padding: 15px; margin-bottom: 15px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); max-width: 80%;">
556
+ <p style="margin-bottom: 10px;">👋 Hello! I'm your Trade Data Assistant powered by Google Gemma-2b.</p>
557
+ <p style="margin-bottom: 5px;">I can help you with:</p>
558
+ <ul style="padding-left: 20px; margin-bottom: 10px;">
559
+ <li>Understanding trade terminology and HS codes</li>
560
+ <li>Exploring interesting trade patterns</li>
561
+ <li>Finding specific trade data</li>
562
+ <li>Interpreting visualization results</li>
563
+ <li>Providing insights about international trade</li>
564
+ </ul>
565
+ <p>How can I assist you today?</p>
566
+ </div>
567
+ </div>
568
+
569
+ <div class="chat-input-area" style="display: flex; padding: 15px; background-color: white; border-top: 1px solid #dee2e6;">
570
+ <input type="text" id="chat-input" class="chat-input" placeholder="Ask me about trade data, HS codes, or how to use this application..." style="flex: 1; padding: 10px 15px; border: 1px solid #ced4da; border-radius: 4px; margin-right: 10px;">
571
+ <button id="chat-send-btn" class="chat-send-btn" style="background-color: #0d6efd; color: white; border: none; border-radius: 4px; padding: 10px 15px; cursor: pointer;">Send</button>
572
+ </div>
573
+ </div>
574
+
575
+ <div class="quick-questions" style="margin-top: 20px;">
576
+ <h5 style="margin-bottom: 15px;">Try asking:</h5>
577
+ <div style="display: flex; flex-wrap: wrap; gap: 10px;">
578
+ <button class="quick-question-btn" style="background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 8px 15px; cursor: pointer;">What are HS codes?</button>
579
+ <button class="quick-question-btn" style="background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 8px 15px; cursor: pointer;">Explain the difference between imports and exports</button>
580
+ <button class="quick-question-btn" style="background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 8px 15px; cursor: pointer;">What does HS code 8471 represent?</button>
581
+ <button class="quick-question-btn" style="background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 8px 15px; cursor: pointer;">How can I interpret trade data?</button>
582
+ <button class="quick-question-btn" style="background-color: #f8f9fa; border: 1px solid #dee2e6; border-radius: 4px; padding: 8px 15px; cursor: pointer;">Recommend interesting trade patterns to explore</button>
583
+ </div>
584
+ </div>
585
+
586
+ <div class="specialized-assistance" style="margin-top: 30px;">
587
+ <h5 style="margin-bottom: 15px;">Specialized Assistance:</h5>
588
+ <div style="display:flex; flex-wrap:wrap; gap:15px;">
589
+ <div style="flex:1; min-width:300px;">
590
+ <h6>HS Code Lookup</h6>
591
+ <div style="display: flex; gap: 10px;">
592
+ <input type="text" id="hs-code-input" placeholder="Enter HS code (e.g. 8471)" style="flex: 1; padding: 8px 12px; border: 1px solid #ced4da; border-radius: 4px;">
593
+ <button id="explain-hs-btn" style="background-color: #28a745; color: white; border: none; border-radius: 4px; padding: 8px 15px; cursor: pointer;">Explain</button>
594
+ </div>
595
+ </div>
596
+
597
+ <div style="flex:1; min-width:300px;">
598
+ <h6>Trade Recommendation</h6>
599
+ <div style="margin-bottom: 10px;">
600
+ <select id="recommendation-country" style="width: 100%; padding: 8px 12px; border: 1px solid #ced4da; border-radius: 4px;">
601
+ <option value="">Select a country (optional)</option>
602
+ <!-- Will be populated from COUNTRY_CODES -->
603
+ </select>
604
+ </div>
605
+ <div style="display: flex; gap: 10px;">
606
+ <input type="text" id="recommendation-product" placeholder="Product (optional)" style="flex: 1; padding: 8px 12px; border: 1px solid #ced4da; border-radius: 4px;">
607
+ <button id="get-recommendation-btn" style="background-color: #17a2b8; color: white; border: none; border-radius: 4px; padding: 8px 15px; cursor: pointer;">Get Insights</button>
608
+ </div>
609
+ </div>
610
+ </div>
611
+ </div>
612
+ </div>
613
+ </div>
614
+
615
+ <!-- Specialized Assistance Panel -->
616
+ <div id="tab-content-specialized" class="tab-content" style="display:none;">
617
+ <div class="container">
618
+ <h4>Specialized Assistance: <span style="font-size:14px;color:#666;font-weight:normal;display:inline-flex;align-items:center;">
619
+ <img src="https://huggingface.co/front/assets/huggingface_logo.svg" alt="Hugging Face" style="height:16px;margin:0 4px;"> Powered by Hugging Face
620
+ </span></h4>
621
+ <div style="display:flex;gap:10px;flex-wrap:wrap;">
622
+ <div style="flex:1;min-width:300px;">
623
+ <h5>HS Code Lookup</h5>
624
+ <div class="input-group">
625
+ <input type="text" id="hs-code-input" placeholder="Enter HS code (e.g. 8471)" class="chat-input" style="width:70%" />
626
+ <button id="explain-hs-btn" class="chat-send-btn" style="width:25%">Explain</button>
627
+ </div>
628
+ </div>
629
+
630
+ <div style="flex:1;min-width:300px;">
631
+ <h5>Trade Recommendation</h5>
632
+ <div class="input-group" style="margin-bottom:10px;">
633
+ <select id="recommendation-country" class="chat-input" style="width:100%">
634
+ <option value="">Select a country (optional)</option>
635
+ <!-- Will be populated from COUNTRY_CODES -->
636
+ </select>
637
+ </div>
638
+ <div class="input-group">
639
+ <input type="text" id="recommendation-product" placeholder="Product (optional)" class="chat-input" style="width:70%" />
640
+ <button id="get-recommendation-btn" class="chat-send-btn" style="width:25%">Get Insights</button>
641
+ </div>
642
+ </div>
643
+ </div>
644
+ </div>
645
+ </div>
646
+ </div>
647
+
648
+ <!-- Animation styles -->
649
+ <style>
650
+ @keyframes spin {
651
+ 0% { transform: rotate(0deg); }
652
+ 100% { transform: rotate(360deg); }
653
+ }
654
+ </style>
655
+
656
+ <!-- Direct tab navigation script -->
657
+ <script>
658
+ document.addEventListener('DOMContentLoaded', function() {
659
+ // Handle iframe loading
660
+ const iframe = document.getElementById('hf-assistant-iframe');
661
+ const loadingIndicator = document.getElementById('assistant-loading');
662
+
663
+ if (iframe && loadingIndicator) {
664
+ iframe.onload = function() {
665
+ loadingIndicator.style.display = 'none';
666
+ };
667
+
668
+ // Set a timeout in case the iframe fails to trigger onload
669
+ setTimeout(function() {
670
+ loadingIndicator.style.display = 'none';
671
+ }, 8000); // Hide after 8 seconds regardless
672
+ }
673
+ // Direct tab navigation logic
674
+ const tabs = document.querySelectorAll('#main-tabs .tab');
675
+ const tabContents = document.querySelectorAll('.tab-content');
676
+
677
+ tabs.forEach(tab => {
678
+ tab.addEventListener('click', function() {
679
+ const tabName = tab.getAttribute('data-tab');
680
+
681
+ // Check if this is the AI Assistant tab
682
+ if (tabName === 'assistant') {
683
+ // Option to redirect directly to Hugging Face Space
684
+ // Uncomment the next line if you want direct redirect
685
+ // window.open('https://huggingface.co/spaces/jomasego/ai-trade-assistant', '_blank');
686
+ }
687
+
688
+ // Hide any visible spinners
689
+ document.querySelectorAll('.spinner').forEach(spinner => {
690
+ spinner.style.display = 'none';
691
+ });
692
+
693
+ // Update active tab
694
+ tabs.forEach(t => {
695
+ t.classList.remove('active');
696
+ t.setAttribute('aria-selected', 'false');
697
+ });
698
+ tab.classList.add('active');
699
+ tab.setAttribute('aria-selected', 'true');
700
+
701
+ // Show corresponding tab content
702
+ tabContents.forEach(panel => {
703
+ if (panel.id === 'tab-content-' + tabName) {
704
+ panel.style.display = 'block';
705
+ } else {
706
+ panel.style.display = 'none';
707
+ }
708
+ });
709
+
710
+ // Focus the active tab
711
+ tab.focus();
712
+ });
713
+
714
+ // Keyboard navigation
715
+ tab.addEventListener('keydown', function(e) {
716
+ if (e.key === 'ArrowRight') {
717
+ e.preventDefault();
718
+ tabs[(idx + 1) % tabs.length].focus();
719
+ } else if (e.key === 'ArrowLeft') {
720
+ e.preventDefault();
721
+ tabs[(idx - 1 + tabs.length) % tabs.length].focus();
722
+ } else if (e.key === 'Enter' || e.key === ' ') {
723
+ e.preventDefault();
724
+ tab.click();
725
+ }
726
+ });
727
+ });
728
+
729
+ // Initial load - make sure the active tab content is visible
730
+ const activeTab = document.querySelector('#main-tabs .tab.active');
731
+ if (activeTab) {
732
+ const tabName = activeTab.getAttribute('data-tab');
733
+ const activePanel = document.getElementById('tab-content-' + tabName);
734
+ if (activePanel) {
735
+ activePanel.style.display = 'block';
736
+ }
737
+ }
738
+ });
739
+ </script>
740
+ </body>
741
+ </html>