pvanand commited on
Commit
4890167
·
verified ·
1 Parent(s): f09387b

Update static/ui/index.html

Browse files
Files changed (1) hide show
  1. static/ui/index.html +282 -107
static/ui/index.html CHANGED
@@ -1,120 +1,295 @@
1
- <!-- static/ui/index.html -->
2
- <!DOCTYPE html>
3
- <html lang="en">
4
  <head>
5
- <meta charset="UTF-8">
6
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Electronics Store</title>
8
- <script src="https://unpkg.com/[email protected]/dist/vue.global.prod.js"></script>
9
- <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/tailwind.min.css" rel="stylesheet">
10
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
11
- <link href="https://cdn.jsdelivr.net/npm/@tailwindcss/typography/dist/typography.min.css" rel="stylesheet">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  </head>
13
- <body class="bg-gray-100">
14
- <div id="app" class="container mx-auto px-4 py-8">
15
- <h1 class="text-4xl font-bold mb-8 text-gray-800">Electronics Store</h1>
16
-
17
- <!-- Filters -->
18
- <div class="mb-6 flex gap-4">
19
- <select v-model="selectedCategory" class="p-2 border rounded-lg">
20
- <option value="">All Categories</option>
21
- <option v-for="category in categories" :key="category" :value="category">{{ category }}</option>
22
- </select>
 
 
 
 
 
23
 
24
- <select v-model="sortBy" class="p-2 border rounded-lg">
25
- <option value="price-asc">Price: Low to High</option>
26
- <option value="price-desc">Price: High to Low</option>
27
- <option value="rating">Rating</option>
28
- </select>
29
  </div>
 
30
 
31
- <!-- Products Grid -->
32
- <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
33
- <div v-for="product in filteredProducts"
34
- :key="product.id"
35
- class="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
36
- <h2 class="text-xl font-semibold mb-2">{{ product.name }}</h2>
37
- <div class="text-sm text-gray-600 mb-4">Category: {{ product.category }}</div>
38
-
39
- <div class="mb-4">
40
- <h3 class="font-semibold mb-2">Specifications:</h3>
41
- <ul class="text-sm">
42
- <li v-for="(value, key) in product.specs" :key="key" class="mb-1">
43
- {{ key }}: {{ value }}
44
- </li>
45
- </ul>
46
- </div>
47
-
48
- <div class="flex justify-between items-center mt-4">
49
- <div class="text-2xl font-bold text-green-600">${{ product.price }}</div>
50
- <div class="text-sm">
51
- <span class="text-yellow-500">★</span>
52
- {{ product.rating }}
53
- </div>
54
- </div>
55
-
56
- <div class="mt-4 text-sm" :class="{'text-red-500': product.stock < 10, 'text-green-500': product.stock >= 10}">
57
- {{ product.stock }} in stock
58
- </div>
59
- </div>
60
  </div>
 
 
 
 
 
61
  </div>
62
 
 
 
 
 
 
 
 
 
63
  <script>
64
- const { createApp, ref, computed } = Vue
65
-
66
- createApp({
67
- setup() {
68
- const products = ref([])
69
- const selectedCategory = ref('')
70
- const sortBy = ref('price-asc')
71
-
72
- // Fetch products from API
73
- fetch('/api/electronics/products')
74
- .then(response => response.json())
75
- .then(data => {
76
- products.value = data.products || []
77
- })
78
- .catch(error => console.error('Error fetching products:', error))
79
-
80
- const categories = computed(() => {
81
- if (!products.value || !products.value.length) return []
82
- return [...new Set(products.value.map(p => p.category))]
83
- })
84
-
85
- const filteredProducts = computed(() => {
86
- if (!products.value || !products.value.length) return []
87
-
88
- let filtered = [...products.value]
89
-
90
- if (selectedCategory.value) {
91
- filtered = filtered.filter(p => p.category === selectedCategory.value)
92
- }
93
-
94
- switch (sortBy.value) {
95
- case 'price-asc':
96
- filtered.sort((a, b) => a.price - b.price)
97
- break
98
- case 'price-desc':
99
- filtered.sort((a, b) => b.price - a.price)
100
- break
101
- case 'rating':
102
- filtered.sort((a, b) => b.rating - a.rating)
103
- break
104
- }
105
-
106
- return filtered
107
- })
108
-
109
- return {
110
- products,
111
- categories,
112
- selectedCategory,
113
- sortBy,
114
- filteredProducts
115
- }
116
  }
117
- }).mount('#app')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
118
  </script>
119
  </body>
120
  </html>
 
1
+ <!doctype html>
2
+ <html class="dark">
 
3
  <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
6
+ <meta name="description" content="Discover amazing ML apps made by the community" />
7
+
8
+ <!-- Existing meta tags remain the same -->
9
+
10
+ <title>AI Web Scraper Chat - Hugging Face Space</title>
11
+
12
+ <!-- Custom CSS -->
13
+ <style>
14
+ :root {
15
+ --primary-color: #4F46E5;
16
+ --secondary-color: #6B7280;
17
+ --background-color: #1F2937;
18
+ --text-color: #F9FAFB;
19
+ --border-color: #374151;
20
+ --hover-color: #6366F1;
21
+ }
22
+
23
+ /* Base styles */
24
+ body {
25
+ font-family: 'Source Sans Pro', -apple-system, BlinkMacSystemFont, sans-serif;
26
+ background-color: var(--background-color);
27
+ color: var(--text-color);
28
+ margin: 0;
29
+ padding: 0;
30
+ min-height: 100vh;
31
+ display: flex;
32
+ flex-direction: column;
33
+ }
34
+
35
+ /* Header styles */
36
+ .main-header {
37
+ background: linear-gradient(to bottom, #2D3748, var(--background-color));
38
+ padding: 1rem 2rem;
39
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
40
+ position: sticky;
41
+ top: 0;
42
+ z-index: 100;
43
+ }
44
+
45
+ .header-container {
46
+ max-width: 1200px;
47
+ margin: 0 auto;
48
+ display: flex;
49
+ justify-content: space-between;
50
+ align-items: center;
51
+ }
52
+
53
+ .logo-section {
54
+ display: flex;
55
+ align-items: center;
56
+ gap: 1rem;
57
+ }
58
+
59
+ .logo {
60
+ width: 40px;
61
+ height: 40px;
62
+ }
63
+
64
+ .site-title {
65
+ font-size: 1.5rem;
66
+ font-weight: 600;
67
+ color: var(--text-color);
68
+ text-decoration: none;
69
+ }
70
+
71
+ /* Navigation styles */
72
+ .main-nav {
73
+ display: flex;
74
+ gap: 2rem;
75
+ align-items: center;
76
+ }
77
+
78
+ .nav-link {
79
+ color: var(--text-color);
80
+ text-decoration: none;
81
+ padding: 0.5rem 1rem;
82
+ border-radius: 4px;
83
+ transition: all 0.2s ease;
84
+ }
85
+
86
+ .nav-link:hover {
87
+ background-color: var(--hover-color);
88
+ }
89
+
90
+ /* Button styles */
91
+ .btn {
92
+ background-color: var(--primary-color);
93
+ color: var(--text-color);
94
+ padding: 0.75rem 1.5rem;
95
+ border: none;
96
+ border-radius: 6px;
97
+ font-weight: 600;
98
+ cursor: pointer;
99
+ transition: all 0.2s ease;
100
+ }
101
+
102
+ .btn:hover {
103
+ background-color: var(--hover-color);
104
+ transform: translateY(-1px);
105
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
106
+ }
107
+
108
+ /* Main content area */
109
+ .main-content {
110
+ flex: 1;
111
+ padding: 2rem;
112
+ max-width: 1200px;
113
+ margin: 0 auto;
114
+ width: 100%;
115
+ }
116
+
117
+ /* Iframe container */
118
+ .space-iframe-container {
119
+ background-color: #ffffff;
120
+ border-radius: 12px;
121
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
122
+ overflow: hidden;
123
+ margin-top: 2rem;
124
+ }
125
+
126
+ .space-iframe {
127
+ width: 100%;
128
+ height: calc(100vh - 200px);
129
+ border: none;
130
+ }
131
+
132
+ /* Loading spinner */
133
+ .spinner-overlay {
134
+ position: fixed;
135
+ top: 0;
136
+ left: 0;
137
+ right: 0;
138
+ bottom: 0;
139
+ background-color: rgba(0, 0, 0, 0.7);
140
+ display: flex;
141
+ justify-content: center;
142
+ align-items: center;
143
+ z-index: 1000;
144
+ }
145
+
146
+ .spinner {
147
+ width: 40px;
148
+ height: 40px;
149
+ border: 4px solid #f3f3f3;
150
+ border-top: 4px solid var(--primary-color);
151
+ border-radius: 50%;
152
+ animation: spin 1s linear infinite;
153
+ }
154
+
155
+ /* Back to top button */
156
+ .back-to-top {
157
+ position: fixed;
158
+ bottom: 2rem;
159
+ right: 2rem;
160
+ background-color: var(--primary-color);
161
+ color: var(--text-color);
162
+ width: 40px;
163
+ height: 40px;
164
+ border-radius: 50%;
165
+ display: flex;
166
+ justify-content: center;
167
+ align-items: center;
168
+ cursor: pointer;
169
+ opacity: 0;
170
+ transition: opacity 0.3s ease;
171
+ border: none;
172
+ }
173
+
174
+ .back-to-top.visible {
175
+ opacity: 1;
176
+ }
177
+
178
+ /* Mobile styles */
179
+ @media (max-width: 768px) {
180
+ .main-nav {
181
+ display: none;
182
+ }
183
+
184
+ .mobile-menu-btn {
185
+ display: block;
186
+ }
187
+
188
+ .main-content {
189
+ padding: 1rem;
190
+ }
191
+
192
+ .space-iframe {
193
+ height: calc(100vh - 150px);
194
+ }
195
+ }
196
+
197
+ /* Animations */
198
+ @keyframes spin {
199
+ 0% { transform: rotate(0deg); }
200
+ 100% { transform: rotate(360deg); }
201
+ }
202
+ </style>
203
  </head>
204
+ <body>
205
+ <!-- Header -->
206
+ <header class="main-header">
207
+ <div class="header-container">
208
+ <div class="logo-section">
209
+ <img src="/front/assets/huggingface_logo-noborder.svg" alt="Hugging Face Logo" class="logo">
210
+ <a href="/" class="site-title">AI Web Scraper Chat</a>
211
+ </div>
212
+
213
+ <nav class="main-nav">
214
+ <a href="#" class="nav-link">Home</a>
215
+ <a href="#" class="nav-link">Documentation</a>
216
+ <a href="#" class="nav-link">Community</a>
217
+ <button class="btn">Get Started</button>
218
+ </nav>
219
 
220
+ <button class="mobile-menu-btn" aria-label="Toggle mobile menu">
221
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
222
+ <path d="M3 12h18M3 6h18M3 18h18"></path>
223
+ </svg>
224
+ </button>
225
  </div>
226
+ </header>
227
 
228
+ <!-- Main content -->
229
+ <main class="main-content">
230
+ <div class="space-iframe-container">
231
+ <iframe
232
+ src="https://elevatics-ai-web-scraper-chat.hf.space/"
233
+ class="space-iframe"
234
+ allow="accelerometer; ambient-light-sensor; autoplay; battery; camera; clipboard-read; clipboard-write; display-capture; document-domain; encrypted-media; fullscreen; geolocation; gyroscope; layout-animations; legacy-image-formats; magnetometer; microphone; midi; oversized-images; payment; picture-in-picture; publickey-credentials-get; sync-xhr; usb; vr; wake-lock; xr-spatial-tracking"
235
+ sandbox="allow-downloads allow-forms allow-modals allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-storage-access-by-user-activation"
236
+ scrolling="no">
237
+ </iframe>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
238
  </div>
239
+ </main>
240
+
241
+ <!-- Loading spinner -->
242
+ <div class="spinner-overlay" id="loading-spinner" style="display: none;">
243
+ <div class="spinner"></div>
244
  </div>
245
 
246
+ <!-- Back to top button -->
247
+ <button class="back-to-top" id="backToTop" aria-label="Back to top">
248
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
249
+ <path d="M12 19V5M5 12l7-7 7 7"></path>
250
+ </svg>
251
+ </button>
252
+
253
+ <!-- JavaScript -->
254
  <script>
255
+ // Loading spinner
256
+ window.addEventListener('load', () => {
257
+ document.getElementById('loading-spinner').style.display = 'none';
258
+ });
259
+
260
+ // Back to top button
261
+ const backToTopButton = document.getElementById('backToTop');
262
+
263
+ window.addEventListener('scroll', () => {
264
+ if (window.scrollY > 300) {
265
+ backToTopButton.classList.add('visible');
266
+ } else {
267
+ backToTopButton.classList.remove('visible');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  }
269
+ });
270
+
271
+ backToTopButton.addEventListener('click', () => {
272
+ window.scrollTo({ top: 0, behavior: 'smooth' });
273
+ });
274
+
275
+ // Mobile menu
276
+ const mobileMenuBtn = document.querySelector('.mobile-menu-btn');
277
+ const mainNav = document.querySelector('.main-nav');
278
+
279
+ mobileMenuBtn.addEventListener('click', () => {
280
+ mainNav.style.display = mainNav.style.display === 'flex' ? 'none' : 'flex';
281
+ });
282
+
283
+ // Responsive iframe height
284
+ function adjustIframeHeight() {
285
+ const iframe = document.querySelector('.space-iframe');
286
+ const viewportHeight = window.innerHeight;
287
+ const headerHeight = document.querySelector('.main-header').offsetHeight;
288
+ iframe.style.height = `${viewportHeight - headerHeight - 40}px`;
289
+ }
290
+
291
+ window.addEventListener('resize', adjustIframeHeight);
292
+ adjustIframeHeight();
293
  </script>
294
  </body>
295
  </html>