privateuserh commited on
Commit
eef08ae
·
verified ·
1 Parent(s): 975c39e

Update main.js

Browse files
Files changed (1) hide show
  1. main.js +159 -0
main.js CHANGED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ // --- CONFIGURATION ---
3
+ const config = {
4
+ // IMPORTANT: Paste your full and correct Cloudflare Worker URL here
5
+ backendUrl: 'https://ar-city-explorer-backend.<your-subdomain>.workers.dev'
6
+ };
7
+
8
+ // --- GLOBAL STATE ---
9
+ let poisData = []; // This will hold all our landmark data from the backend
10
+ let arActive = false;
11
+
12
+ // --- DOM ELEMENT SELECTORS ---
13
+ const arToggle = document.getElementById('arToggle');
14
+ const arViewport = document.getElementById('arViewport');
15
+ const normalView = document.getElementById('normalView');
16
+ const aiAssistant = document.getElementById('aiAssistant');
17
+ const userInput = document.getElementById('userInput');
18
+ const sendBtn = document.getElementById('sendBtn');
19
+ const objectModal = document.getElementById('objectModal');
20
+ const objectTitle = document.getElementById('objectTitle');
21
+ const objectDescription = document.getElementById('objectDescription');
22
+ const objectImage = document.getElementById('objectImage');
23
+ const closeObjectModal = document.getElementById('closeObjectModal');
24
+
25
+ // --- CORE FUNCTIONS ---
26
+
27
+ function toggleARView(showAR) {
28
+ arActive = showAR;
29
+ if (arActive) {
30
+ normalView.classList.add('hidden');
31
+ arViewport.classList.remove('hidden');
32
+ arToggle.innerHTML = '<i class="fas fa-times mr-1"></i> Exit AR';
33
+ // Fetch data only if it hasn't been fetched yet
34
+ if (poisData.length === 0) {
35
+ fetchPoisAndCreateAREntities();
36
+ }
37
+ } else {
38
+ arViewport.classList.add('hidden');
39
+ normalView.classList.remove('hidden');
40
+ arToggle.innerHTML = '<i class="fas fa-vr-cardboard mr-1"></i> AR Mode';
41
+ }
42
+ }
43
+
44
+ function fetchPoisAndCreateAREntities() {
45
+ console.log('Fetching POIs from backend...');
46
+ fetch(`${config.backendUrl}/api/pois`)
47
+ .then(response => {
48
+ if (!response.ok) throw new Error(`Network error: ${response.statusText}`);
49
+ return response.json();
50
+ })
51
+ .then(pois => {
52
+ console.log('POIs received:', pois);
53
+ poisData = pois; // Store the data globally
54
+ const scene = document.querySelector('a-scene');
55
+ if (!scene) return console.error('A-Frame scene not found!');
56
+
57
+ pois.forEach(poi => {
58
+ const entity = document.createElement('a-entity');
59
+ entity.setAttribute('gps-new-entity-place', {
60
+ latitude: poi.latitude,
61
+ longitude: poi.longitude
62
+ });
63
+
64
+ const box = document.createElement('a-box');
65
+ box.setAttribute('material', 'color: red; opacity: 0.7;');
66
+ box.setAttribute('scale', '10 10 10');
67
+ box.setAttribute('position', '0 5 0');
68
+ box.setAttribute('data-poi-id', poi.id); // Set ID for click detection
69
+ entity.appendChild(box);
70
+
71
+ const text = document.createElement('a-text');
72
+ text.setAttribute('value', poi.name);
73
+ text.setAttribute('look-at', '[gps-new-camera]');
74
+ text.setAttribute('scale', '50 50 50');
75
+ text.setAttribute('position', '0 15 0');
76
+ entity.appendChild(text);
77
+
78
+ scene.appendChild(entity);
79
+ });
80
+ })
81
+ .catch(error => {
82
+ console.error('Failed to load POIs:', error);
83
+ alert('Could not load city data. Check your connection and the backend URL.');
84
+ toggleARView(false);
85
+ });
86
+ }
87
+
88
+ // --- MODAL AND UI FUNCTIONS ---
89
+
90
+ function showObjectInfo(poiId) {
91
+ const poi = poisData.find(p => p.id === poiId);
92
+ if (!poi) return;
93
+ objectTitle.textContent = poi.name;
94
+ objectDescription.textContent = poi.description || "No description available.";
95
+ objectImage.src = `https://via.placeholder.com/300x200?text=${encodeURIComponent(poi.name)}`;
96
+ objectModal.classList.remove('hidden');
97
+ }
98
+
99
+ function addUserMessage(message) {
100
+ const chatContainer = aiAssistant.querySelector('.flex-col');
101
+ const msg = `<div class="ai-message user-message"><p>${message}</p></div>`;
102
+ chatContainer.insertAdjacentHTML('beforeend', msg);
103
+ aiAssistant.scrollTop = aiAssistant.scrollHeight;
104
+ }
105
+
106
+ function addAIMessage(message) {
107
+ const chatContainer = aiAssistant.querySelector('.flex-col');
108
+ const msg = `<div class="ai-message assistant-message"><div class="font-bold text-indigo-800 mb-1">AR Guide</div><p>${message}</p></div>`;
109
+ chatContainer.insertAdjacentHTML('beforeend', msg);
110
+ aiAssistant.scrollTop = aiAssistant.scrollHeight;
111
+ }
112
+
113
+ function handleSearch() {
114
+ const searchTerm = userInput.value.trim();
115
+ if (!searchTerm) return;
116
+ addUserMessage(searchTerm);
117
+ userInput.value = '';
118
+
119
+ if (poisData.length === 0) {
120
+ addAIMessage("I'm still loading location data. Please try again in a moment.");
121
+ return;
122
+ }
123
+
124
+ const results = poisData.filter(poi =>
125
+ poi.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
126
+ (poi.description && poi.description.toLowerCase().includes(searchTerm.toLowerCase()))
127
+ );
128
+
129
+ if (results.length > 0) {
130
+ let response = `I found ${results.length} result(s):<ul>`;
131
+ results.forEach(poi => { response += `<li class="mt-2 list-disc list-inside">${poi.name}</li>`; });
132
+ response += "</ul>";
133
+ addAIMessage(response);
134
+ } else {
135
+ addAIMessage(`Sorry, I couldn't find anything matching "${searchTerm}".`);
136
+ }
137
+ }
138
+
139
+ // --- EVENT LISTENERS ---
140
+
141
+ arToggle.addEventListener('click', () => toggleARView(!arActive));
142
+
143
+ document.querySelector('a-scene').addEventListener('click', (event) => {
144
+ if (event.target.hasAttribute('data-poi-id')) {
145
+ const poiId = parseInt(event.target.getAttribute('data-poi-id'), 10);
146
+ showObjectInfo(poiId);
147
+ }
148
+ });
149
+
150
+ closeObjectModal.addEventListener('click', () => objectModal.classList.add('hidden'));
151
+
152
+ sendBtn.addEventListener('click', handleSearch);
153
+ userInput.addEventListener('keypress', (e) => {
154
+ if (e.key === 'Enter') handleSearch();
155
+ });
156
+
157
+ // Initial fetch of data so the search bar works immediately
158
+ fetchPoisAndCreateAREntities();
159
+ });