privateuserh commited on
Commit
1353374
·
verified ·
1 Parent(s): b01f4a3

Delete index.html

Browse files
Files changed (1) hide show
  1. index.html +0 -672
index.html DELETED
@@ -1,672 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>AR City Explorer | Smart Glasses Companion</title>
7
- <script src="https://cdn.tailwindcss.com"></script>
8
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe.min.js"></script>
9
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/mindar-image-aframe.prod.js"></script>
10
- <script src="https://cdn.jsdelivr.net/npm/speech-recognition@latest/dist/speech-recognition.min.js"></script>
11
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
12
- <style>
13
- @keyframes pulse {
14
- 0% { opacity: 0.6; }
15
- 50% { opacity: 1; }
16
- 100% { opacity: 0.6; }
17
- }
18
- .pulse {
19
- animation: pulse 2s infinite;
20
- }
21
- .ar-overlay {
22
- position: fixed;
23
- top: 0;
24
- left: 0;
25
- width: 100%;
26
- height: 100%;
27
- background-color: rgba(0,0,0,0.8);
28
- z-index: 9999;
29
- display: flex;
30
- flex-direction: column;
31
- justify-content: center;
32
- align-items: center;
33
- color: white;
34
- }
35
- .ar-object {
36
- position: absolute;
37
- background-color: rgba(255,255,255,0.2);
38
- border: 2px solid rgba(255,255,255,0.5);
39
- border-radius: 8px;
40
- padding: 10px;
41
- color: white;
42
- font-size: 14px;
43
- pointer-events: all;
44
- transition: all 0.3s ease;
45
- }
46
- .ar-object:hover {
47
- background-color: rgba(255,255,255,0.3);
48
- transform: scale(1.05);
49
- }
50
- .ai-message {
51
- max-width: 80%;
52
- margin-bottom: 10px;
53
- padding: 12px;
54
- border-radius: 18px;
55
- position: relative;
56
- }
57
- .user-message {
58
- background-color: #3b82f6;
59
- color: white;
60
- align-self: flex-end;
61
- border-bottom-right-radius: 4px;
62
- }
63
- .assistant-message {
64
- background-color: #f3f4f6;
65
- color: #111827;
66
- align-self: flex-start;
67
- border-bottom-left-radius: 4px;
68
- }
69
- .glasses-pairing {
70
- background: linear-gradient(135deg, #1e3a8a 0%, #3b82f6 100%);
71
- }
72
- .object-highlight {
73
- box-shadow: 0 0 20px 5px rgba(59, 130, 246, 0.7);
74
- }
75
- #arViewport {
76
- width: 100%;
77
- height: 100%;
78
- position: relative;
79
- overflow: hidden;
80
- }
81
- .loading-spinner {
82
- width: 50px;
83
- height: 50px;
84
- border: 5px solid rgba(255,255,255,0.3);
85
- border-radius: 50%;
86
- border-top-color: #fff;
87
- animation: spin 1s ease-in-out infinite;
88
- }
89
- @keyframes spin {
90
- to { transform: rotate(360deg); }
91
- }
92
- </style>
93
- </head>
94
- <body class="bg-gray-100 font-sans">
95
- <!-- Main App Container -->
96
- <div class="max-w-md mx-auto bg-white shadow-lg rounded-lg overflow-hidden min-h-screen flex flex-col">
97
- <!-- Header -->
98
- <header class="bg-indigo-900 text-white p-4 flex justify-between items-center">
99
- <div class="flex items-center space-x-2">
100
- <i class="fas fa-glasses text-2xl"></i>
101
- <h1 class="text-xl font-bold">AR City Explorer</h1>
102
- </div>
103
- <div class="flex space-x-3">
104
- <button id="arToggle" class="bg-indigo-700 hover:bg-indigo-600 px-3 py-1 rounded-full text-sm flex items-center">
105
- <i class="fas fa-vr-cardboard mr-1"></i> AR Mode
106
- </button>
107
- <button id="settingsBtn" class="bg-indigo-700 hover:bg-indigo-600 px-3 py-1 rounded-full text-sm">
108
- <i class="fas fa-cog"></i>
109
- </button>
110
- </div>
111
- </header>
112
-
113
- <!-- Main Content Area -->
114
- <main class="flex-1 overflow-hidden">
115
- <!-- AR Viewport (hidden by default) -->
116
- <div id="arViewport" class="hidden relative">
117
- <div id="arScene" class="absolute inset-0"></div>
118
- <div id="arOverlay" class="ar-overlay hidden">
119
- <div class="loading-spinner"></div>
120
- <p class="mt-4">Initializing AR environment...</p>
121
- <p class="text-sm text-gray-300 mt-2">Point your device at objects to scan</p>
122
- </div>
123
- <div id="arObjects" class="absolute inset-0"></div>
124
- </div>
125
-
126
- <!-- Normal View (shown by default) -->
127
- <div id="normalView" class="h-full flex flex-col">
128
- <!-- AI Assistant Chat -->
129
- <div id="aiAssistant" class="flex-1 overflow-y-auto p-4 bg-gray-50">
130
- <div class="flex flex-col space-y-2">
131
- <div class="ai-message assistant-message">
132
- <div class="font-bold text-indigo-800 mb-1">AR Guide</div>
133
- <p>Hello! I'm your AR assistant. How can I help you explore the city today?</p>
134
- <div class="mt-2 flex flex-wrap gap-2">
135
- <button class="quick-action bg-indigo-100 text-indigo-800 px-3 py-1 rounded-full text-xs">
136
- Nearby landmarks
137
- </button>
138
- <button class="quick-action bg-indigo-100 text-indigo-800 px-3 py-1 rounded-full text-xs">
139
- Find restaurants
140
- </button>
141
- <button class="quick-action bg-indigo-100 text-indigo-800 px-3 py-1 rounded-full text-xs">
142
- History tour
143
- </button>
144
- </div>
145
- </div>
146
- </div>
147
- </div>
148
-
149
- <!-- User Input -->
150
- <div class="p-4 border-t border-gray-200 bg-white">
151
- <div class="flex space-x-2">
152
- <input type="text" id="userInput" placeholder="Ask about places, history, or services..."
153
- class="flex-1 border border-gray-300 rounded-full px-4 py-2 focus:outline-none focus:ring-2 focus:ring-indigo-500">
154
- <button id="sendBtn" class="bg-indigo-600 text-white rounded-full w-10 h-10 flex items-center justify-center">
155
- <i class="fas fa-paper-plane"></i>
156
-
157
-
158
- <script>
159
- // DOM Elements
160
- const arToggle = document.getElementById('arToggle');
161
- const arViewport = document.getElementById('arViewport');
162
- const normalView = document.getElementById('normalView');
163
- const arOverlay = document.getElementById('arOverlay');
164
- const glassesModal = document.getElementById('glassesModal');
165
- const pairBtn = document.getElementById('pairBtn');
166
- const pairingStatus = document.getElementById('pairingStatus');
167
- const closeGlassesModal = document.getElementById('closeGlassesModal');
168
- const glassesBtn = document.getElementById('glassesBtn');
169
- const objectModal = document.getElementById('objectModal');
170
- const closeObjectModal = document.getElementById('closeObjectModal');
171
- const settingsBtn = document.getElementById('settingsBtn');
172
- const settingsModal = document.getElementById('settingsModal');
173
- const closeSettingsModal = document.getElementById('closeSettingsModal');
174
- const manageGlassesBtn = document.getElementById('manageGlassesBtn');
175
- const userInput = document.getElementById('userInput');
176
- const sendBtn = document.getElementById('sendBtn');
177
- const voiceBtn = document.getElementById('voiceBtn');
178
- const aiAssistant = document.getElementById('aiAssistant');
179
-
180
- // Sample AR objects data (in a real app, this would come from an API)
181
- const arObjects = [
182
- {
183
- id: 'landmark-1',
184
- type: 'landmark',
185
- title: 'Old Town Hall',
186
- description: 'Built in 1892, this historic building served as the city hall until 1978. Notable for its Victorian architecture and the clock tower that still keeps perfect time.',
187
- image: 'https://images.unsplash.com/photo-1564501049412-61c2a3083791?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80',
188
- position: { x: 30, y: 40 },
189
- vendors: []
190
- },
191
- {
192
- id: 'landmark-2',
193
- type: 'landmark',
194
- title: 'Liberty Statue',
195
- description: 'Erected in 1921 to commemorate the city\'s role in the independence movement. The statue stands 15 meters tall and is made of bronze.',
196
- image: 'https://images.unsplash.com/photo-1582721478829-efeab1c87aec?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80',
197
- position: { x: 70, y: 60 },
198
- vendors: []
199
- },
200
- {
201
- id: 'sign-1',
202
- type: 'sign',
203
- title: 'Historic District Sign',
204
- description: 'Marks the boundary of the city\'s historic preservation area. The district contains over 50 buildings from the 19th century.',
205
- image: 'https://images.unsplash.com/photo-1614624532983-4fe9c6aff2f5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80',
206
- position: { x: 50, y: 20 },
207
- vendors: []
208
- },
209
- {
210
- id: 'vendor-1',
211
- type: 'vendor',
212
- title: 'Heritage Café',
213
- description: 'A charming café housed in a restored 19th-century building. Known for its artisanal coffee and homemade pastries.',
214
- image: 'https://images.unsplash.com/photo-1555396273-367ea4eb4db5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80',
215
- position: { x: 40, y: 70 },
216
- vendors: [
217
- { id: 'item-1', name: 'Artisan Coffee', price: '$4.50', description: 'Locally roasted coffee beans' },
218
- { id: 'item-2', name: 'Croissant', price: '$3.25', description: 'Freshly baked butter croissant' },
219
- { id: 'item-3', name: 'Sandwich', price: '$7.50', description: 'Daily special with local ingredients' }
220
- ]
221
- },
222
- {
223
- id: 'vendor-2',
224
- type: 'vendor',
225
- title: 'Souvenir Shop',
226
- description: 'Offers locally made crafts, postcards, and memorabilia that celebrate the city\'s history.',
227
- image: 'https://images.unsplash.com/photo-1607083206869-4c767bc49c4b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1000&q=80',
228
- position: { x: 60, y: 50 },
229
- vendors: [
230
- { id: 'item-4', name: 'City Guidebook', price: '$12.99', description: 'Detailed history and walking tours' },
231
- { id: 'item-5', name: 'Postcard Set', price: '$5.50', description: '6 vintage-style postcards' },
232
- { id: 'item-6', name: 'Handmade Mug', price: '$15.00', description: 'Ceramic mug with city skyline' }
233
- ]
234
- }
235
- ];
236
-
237
- // Sample AI responses
238
- const aiResponses = [
239
- "The Old Town Hall is located about 200 meters north of your current position. It was built in 1892 and features remarkable Victorian architecture.",
240
- "The Liberty Statue commemorates the city's role in the independence movement. It's a popular photo spot for visitors.",
241
- "You're currently in the historic district which contains over 50 preserved buildings from the 19th century.",
242
- "The Heritage Café is known for its artisanal coffee and homemade pastries. Would you like to see their menu?",
243
- "The Souvenir Shop offers locally made crafts and memorabilia. They have guidebooks, postcards, and handmade items."
244
- ];
245
-
246
- // Initialize AR
247
- let arActive = false;
248
- let glassesPaired = false;
249
-
250
- // Toggle AR Mode
251
- arToggle.addEventListener('click', () => {
252
- if (!glassesPaired) {
253
- showGlassesModal();
254
- return;
255
- }
256
-
257
- arActive = !arActive;
258
-
259
- if (arActive) {
260
- // Enter AR Mode
261
- normalView.classList.add('hidden');
262
- arViewport.classList.remove('hidden');
263
- arOverlay.classList.remove('hidden');
264
- arToggle.innerHTML = '<i class="fas fa-times mr-1"></i> Exit AR';
265
-
266
- // Simulate AR initialization
267
- setTimeout(() => {
268
- arOverlay.classList.add('hidden');
269
- initializeARScene();
270
- }, 2000);
271
- } else {
272
- // Exit AR Mode
273
- normalView.classList.remove('hidden');
274
- arViewport.classList.add('hidden');
275
- arToggle.innerHTML = '<i class="fas fa-vr-cardboard mr-1"></i> AR Mode';
276
- clearARScene();
277
- }
278
- });
279
-
280
- // Initialize AR Scene
281
- function initializeARScene() {
282
- const arObjectsContainer = document.getElementById('arObjects');
283
-
284
- // Clear previous objects
285
- arObjectsContainer.innerHTML = '';
286
-
287
- // Create AR objects
288
- arObjects.forEach(obj => {
289
- const arElement = document.createElement('div');
290
- arElement.className = 'ar-object';
291
- arElement.style.left = `${obj.position.x}%`;
292
- arElement.style.top = `${obj.position.y}%`;
293
- arElement.dataset.id = obj.id;
294
-
295
- // Set icon based on type
296
- let icon, bgColor;
297
- if (obj.type === 'landmark') {
298
- icon = '<i class="fas fa-landmark mr-1"></i>';
299
- bgColor = 'rgba(220, 38, 38, 0.7)';
300
- } else if (obj.type === 'sign') {
301
- icon = '<i class="fas fa-sign mr-1"></i>';
302
- bgColor = 'rgba(234, 88, 12, 0.7)';
303
- } else if (obj.type === 'vendor') {
304
- icon = '<i class="fas fa-store mr-1"></i>';
305
- bgColor = 'rgba(22, 163, 74, 0.7)';
306
- }
307
-
308
- arElement.style.backgroundColor = bgColor;
309
- arElement.innerHTML = `${icon} ${obj.title}`;
310
-
311
- // Add click event
312
- arElement.addEventListener('click', () => showObjectInfo(obj));
313
-
314
- arObjectsContainer.appendChild(arElement);
315
- });
316
- // --- Modal Functionality ---
317
-
318
- const objectModal = document.getElementById('objectModal');
319
- const objectTitle = document.getElementById('objectTitle');
320
- const objectDescription = document.getElementById('objectDescription');
321
- const objectImage = document.getElementById('objectImage');
322
- const closeObjectModal = document.getElementById('closeObjectModal');
323
-
324
-
325
- function showObjectInfo(poiId) {
326
- // Find the specific POI from our data array using its ID
327
- const poi = poisData.find(p => p.id === poiId);
328
- if (!poi) {
329
- console.error("Could not find POI data for ID:", poiId);
330
- return;
331
- }
332
-
333
- console.log("Showing info for:", poi.name);
334
-
335
- // Populate the modal with data from the POI object
336
- objectTitle.textContent = poi.name;
337
- objectDescription.textContent = poi.description || "No description available.";
338
-
339
- // Use a placeholder image if no asset_url is provided
340
- // In a real app, your 'asset_url' might point to a specific image for the landmark
341
- objectImage.src = `https://via.placeholder.com/300x200?text=${encodeURIComponent(poi.name)}`;
342
-
343
- // --- Future Vendor Logic ---
344
- // This is where you would check for vendor info from your POI data
345
- // and show/hide the vendorSection just like your original code intended.
346
- // For now, we'll keep it hidden.
347
- document.getElementById('vendorSection').classList.add('hidden');
348
-
349
- // Display the modal by removing the 'hidden' class
350
- objectModal.classList.remove('hidden');
351
- }
352
-
353
- // Add an event listener to the modal's close button
354
- closeObjectModal.addEventListener('click', () => {
355
- objectModal.classList.add('hidden');
356
- });
357
-
358
- // Also close the modal if the user clicks on the dark background
359
- objectModal.addEventListener('click', (e) => {
360
- if (e.target === objectModal) {
361
- objectModal.classList.add('hidden');
362
- }
363
- });
364
-
365
- // Simulate object recognition highlighting
366
- setTimeout(() => {
367
- const firstObject = document.querySelector('.ar-object');
368
- if (firstObject) {
369
- firstObject.classList.add('object-highlight');
370
- setTimeout(() => {
371
- firstObject.classList.remove('object-highlight');
372
- }, 3000);
373
- }
374
- }, 1000);
375
- }
376
-
377
- // Clear AR Scene
378
- function clearARScene() {
379
- const arObjectsContainer = document.getElementById('arObjects');
380
- arObjectsContainer.innerHTML = '';
381
- }
382
-
383
- // Show object info modal
384
- function showObjectInfo(obj) {
385
- document.getElementById('objectTitle').textContent = obj.title;
386
- document.getElementById('objectImage').src = obj.image;
387
- document.getElementById('objectDescription').textContent = obj.description;
388
-
389
- // Show vendor section if applicable
390
- const vendorSection = document.getElementById('vendorSection');
391
- if (obj.vendors && obj.vendors.length > 0) {
392
- vendorSection.classList.remove('hidden');
393
- const vendorItemsContainer = vendorSection.querySelector('.space-y-2');
394
- vendorItemsContainer.innerHTML = '';
395
-
396
- obj.vendors.forEach(vendor => {
397
- const itemElement = document.createElement('div');
398
- itemElement.className = 'flex justify-between items-center p-2 bg-gray-100 rounded';
399
- itemElement.innerHTML = `
400
- <div>
401
- <div class="font-medium">${vendor.name}</div>
402
- <div class="text-sm text-gray-600">${vendor.description}</div>
403
- </div>
404
- <div class="font-bold">${vendor.price}</div>
405
- `;
406
- vendorItemsContainer.appendChild(itemElement);
407
- });
408
- } else {
409
- vendorSection.classList.add('hidden');
410
- }
411
-
412
- objectModal.classList.remove('hidden');
413
- }
414
-
415
- // Glasses pairing functionality
416
- function showGlassesModal() {
417
- glassesModal.classList.remove('hidden');
418
- }
419
-
420
- closeGlassesModal.addEventListener('click', () => {
421
- glassesModal.classList.add('hidden');
422
- });
423
-
424
- pairBtn.addEventListener('click', () => {
425
- pairingStatus.classList.remove('hidden');
426
- pairBtn.disabled = true;
427
-
428
- // Simulate pairing process
429
- setTimeout(() => {
430
- pairingStatus.innerHTML = '<div class="flex items-center justify-center text-green-300"><i class="fas fa-check-circle mr-2"></i> Successfully paired!</div>';
431
- setTimeout(() => {
432
- glassesModal.classList.add('hidden');
433
- pairingStatus.classList.add('hidden');
434
- pairBtn.disabled = false;
435
- glassesPaired = true;
436
-
437
- // Update glasses button
438
- const glassesIcon = glassesBtn.querySelector('i');
439
- glassesIcon.classList.remove('text-gray-500');
440
- glassesIcon.classList.add('text-indigo-600');
441
-
442
- // Show success message
443
- addAIMessage("Your AR glasses have been successfully paired! You can now enter AR mode.");
444
- }, 1000);
445
- }, 2000);
446
- });
447
-
448
- glassesBtn.addEventListener('click', showGlassesModal);
449
-
450
- // Settings modal
451
- settingsBtn.addEventListener('click', () => {
452
- settingsModal.classList.remove('hidden');
453
- });
454
-
455
- closeSettingsModal.addEventListener('click', () => {
456
- settingsModal.classList.add('hidden');
457
- });
458
- <body class="bg-gray-100 font-sans">
459
- <div class="max-w-md mx-auto bg-white shadow-lg rounded-lg overflow-hidden min-h-screen flex flex-col">
460
- <header class="bg-indigo-900 text-white p-4 flex justify-between items-center">
461
- </header>
462
-
463
- <main class="flex-1 overflow-hidden">
464
- <div id="arViewport" class="hidden relative">
465
-
466
- <a-scene id="arScene" vr-mode-ui="enabled: false" arjs='sourceType: webcam; videoTexture: true; debugUIEnabled: false;'>
467
- <a-camera gps-new-camera='gpsMinDistance: 5'></a-camera>
468
- </a-scene>
469
-
470
- <div id="arOverlay" class="ar-overlay hidden">
471
- </div>
472
- </div>
473
-
474
- <div id="normalView" class="h-full flex flex-col">
475
- </div>
476
- </main>
477
-
478
- <nav class="bg-white border-t border-gray-200 p-2 flex justify-around">
479
- </nav>
480
- </div>
481
-
482
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe.min.js"></script>
483
- <script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar-nft.js"></script>
484
-
485
- <script>
486
- document.addEventListener('DOMContentLoaded', () => {
487
-
488
- // --- CONFIGURATION ---
489
- const config = {
490
- // FIX: USE YOUR FULL AND CORRECT CLOUDFLARE URL HERE
491
- backendUrl: 'https://ar-city-explorer-backend.<your-subdomain>.workers.dev'
492
- };
493
-
494
- // --- ELEMENT SELECTORS ---
495
- const arViewport = document.getElementById('arViewport');
496
- const normalView = document.getElementById('normalView');
497
- const arToggle = document.getElementById('arToggle');
498
- const aiAssistant = document.getElementById('aiAssistant');
499
- const userInput = document.getElementById('userInput');
500
- const sendBtn = document.getElementById('sendBtn');
501
- // ... (add all your other getElementById selectors here for modals, buttons etc.)
502
-
503
- let poisData = []; // To store data from the backend
504
-
505
- // --- CORE FUNCTIONS ---
506
-
507
- function toggleARView(showAR) {
508
- if (showAR) {
509
- normalView.classList.add('hidden');
510
- arViewport.classList.remove('hidden');
511
- // Only fetch data if we don't have it already
512
- if (poisData.length === 0) {
513
- fetchPoisAndCreateAREntities();
514
- }
515
- } else {
516
- arViewport.classList.add('hidden');
517
- normalView.classList.remove('hidden');
518
- }
519
- }
520
-
521
- function fetchPoisAndCreateAREntities() {
522
- console.log('Fetching POIs from backend...');
523
-
524
- fetch(`${config.backendUrl}/api/pois`)
525
- .then(response => {
526
- if (!response.ok) {
527
- throw new Error(`Network response was not ok: ${response.statusText}`);
528
- }
529
- return response.json();
530
- })
531
- .then(pois => {
532
- console.log('POIs received:', pois);
533
- poisData = pois; // Store the data
534
- const scene = document.querySelector('a-scene');
535
-
536
- if (!scene) {
537
- console.error('Could not find <a-scene> element.');
538
- return;
539
- }
540
-
541
- pois.forEach(poi => {
542
- const entity = document.createElement('a-entity');
543
- entity.setAttribute('gps-new-entity-place', {
544
- latitude: poi.latitude,
545
- longitude: poi.longitude
546
- });
547
-
548
- // Add visual components (e.g., a box)
549
- const box = document.createElement('a-box');
550
- box.setAttribute('material', 'color: red');
551
- box.setAttribute('scale', '10 10 10');
552
- box.setAttribute('position', '0 5 0');
553
-
554
- // Make the box clickable
555
- box.setAttribute('data-poi-id', poi.id); // Store poi id on the box
556
-
557
- entity.appendChild(box);
558
-
559
- const text = document.createElement('a-text');
560
- text.setAttribute('value', poi.name);
561
- text.setAttribute('look-at', '[gps-new-camera]');
562
- text.setAttribute('scale', '50 50 50');
563
- text.setAttribute('position', '0 15 0');
564
- entity.appendChild(text);
565
-
566
- scene.appendChild(entity);
567
- });
568
- })
569
- .catch(error => {
570
- console.error('Failed to load or process POIs:', error);
571
- alert('Could not load city data. Please check your connection and try again.');
572
- toggleARView(false); // Switch back to normal view on error
573
- });
574
- }
575
-
576
- function showObjectInfo(poiId) {
577
- const poi = poisData.find(p => p.id === poiId);
578
- if(!poi) return;
579
-
580
- console.log("Showing info for:", poi.name);
581
- // This is where you would populate and show your objectModal
582
- // document.getElementById('objectTitle').textContent = poi.name;
583
- // document.getElementById('objectDescription').textContent = poi.description;
584
- // ... etc.
585
- }
586
-
587
-
588
- // --- EVENT LISTENERS ---
589
-
590
- arToggle.addEventListener('click', () => toggleARView(true));
591
-
592
- // Add a listener for clicks within the AR scene
593
- document.querySelector('a-scene').addEventListener('click', (event) => {
594
- // Check if the clicked element is one of our boxes
595
- if (event.target.hasAttribute('data-poi-id')) {
596
- const poiId = parseInt(event.target.getAttribute('data-poi-id'), 10);
597
- showObjectInfo(poiId);
598
- }
599
- });
600
-
601
- // Add all your other event listeners for the UI here
602
- // sendBtn.addEventListener('click', () => { ... });
603
- // voiceBtn.addEventListener('click', () => { ... });
604
- // --- AI Assistant and Search Functionality ---
605
-
606
- function addUserMessage(message) {
607
- const chatContainer = aiAssistant.querySelector('.flex-col');
608
- const messageElement = document.createElement('div');
609
- messageElement.className = 'ai-message user-message';
610
- messageElement.innerHTML = `<p>${message}</p>`;
611
- chatContainer.appendChild(messageElement);
612
- aiAssistant.scrollTop = aiAssistant.scrollHeight; // Auto-scroll
613
- }
614
-
615
- function addAIMessage(message) {
616
- const chatContainer = aiAssistant.querySelector('.flex-col');
617
- const messageElement = document.createElement('div');
618
- messageElement.className = 'ai-message assistant-message';
619
- messageElement.innerHTML = `
620
- <div class="font-bold text-indigo-800 mb-1">AR Guide</div>
621
- <p>${message}</p>
622
- `;
623
- chatContainer.appendChild(messageElement);
624
- aiAssistant.scrollTop = aiAssistant.scrollHeight; // Auto-scroll
625
- }
626
-
627
- // Event listener for the send button
628
- sendBtn.addEventListener('click', () => {
629
- const searchTerm = userInput.value.trim();
630
- if (!searchTerm) return;
631
-
632
- addUserMessage(searchTerm);
633
- userInput.value = '';
634
-
635
- // --- NEW SEARCH LOGIC ---
636
- // Make the search case-insensitive
637
- const lowerCaseSearchTerm = searchTerm.toLowerCase();
638
-
639
- // Filter the POI data we got from the backend
640
- const results = poisData.filter(poi =>
641
- poi.name.toLowerCase().includes(lowerCaseSearchTerm) ||
642
- (poi.description && poi.description.toLowerCase().includes(lowerCaseSearchTerm))
643
- );
644
-
645
- // Respond based on the search results
646
- if (results.length > 0) {
647
- let responseMessage = `I found ${results.length} location(s) matching your search:<ul>`;
648
- results.forEach(poi => {
649
- responseMessage += `<li class="mt-2 list-disc list-inside">${poi.name}</li>`;
650
- });
651
- responseMessage += "</ul>";
652
- addAIMessage(responseMessage);
653
- } else {
654
- addAIMessage(`Sorry, I couldn't find any locations matching "${searchTerm}". Try searching for something else.`);
655
- }
656
- });
657
-
658
- // Also allow pressing Enter to search
659
- userInput.addEventListener('keypress', (e) => {
660
- if (e.key === 'Enter') {
661
- sendBtn.click();
662
- }
663
- });
664
- });
665
- </script>
666
-
667
- </body>
668
- </html>
669
- </body>
670
- </html>
671
- <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=privateuserh/smarar" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
672
- </html>