document.addEventListener('DOMContentLoaded', () => { // --- CONFIGURATION --- const config = { // IMPORTANT: Paste your full and correct Cloudflare Worker URL here backendUrl: 'https://ar-city-explorer-backend..workers.dev' }; // --- GLOBAL STATE --- let poisData = []; // This will hold all our landmark data from the backend let arActive = false; // --- DOM ELEMENT SELECTORS --- const arToggle = document.getElementById('arToggle'); const arViewport = document.getElementById('arViewport'); const normalView = document.getElementById('normalView'); const aiAssistant = document.getElementById('aiAssistant'); const userInput = document.getElementById('userInput'); const sendBtn = document.getElementById('sendBtn'); const objectModal = document.getElementById('objectModal'); const objectTitle = document.getElementById('objectTitle'); const objectDescription = document.getElementById('objectDescription'); const objectImage = document.getElementById('objectImage'); const closeObjectModal = document.getElementById('closeObjectModal'); // --- CORE FUNCTIONS --- function toggleARView(showAR) { arActive = showAR; if (arActive) { normalView.classList.add('hidden'); arViewport.classList.remove('hidden'); arToggle.innerHTML = ' Exit AR'; // Fetch data only if it hasn't been fetched yet if (poisData.length === 0) { fetchPoisAndCreateAREntities(); } } else { arViewport.classList.add('hidden'); normalView.classList.remove('hidden'); arToggle.innerHTML = ' AR Mode'; } } function fetchPoisAndCreateAREntities() { console.log('Fetching POIs from backend...'); fetch(`${config.backendUrl}/api/pois`) .then(response => { if (!response.ok) throw new Error(`Network error: ${response.statusText}`); return response.json(); }) .then(pois => { console.log('POIs received:', pois); poisData = pois; // Store the data globally const scene = document.querySelector('a-scene'); if (!scene) return console.error('A-Frame scene not found!'); pois.forEach(poi => { const entity = document.createElement('a-entity'); entity.setAttribute('gps-new-entity-place', { latitude: poi.latitude, longitude: poi.longitude }); const box = document.createElement('a-box'); box.setAttribute('material', 'color: red; opacity: 0.7;'); box.setAttribute('scale', '10 10 10'); box.setAttribute('position', '0 5 0'); box.setAttribute('data-poi-id', poi.id); // Set ID for click detection entity.appendChild(box); const text = document.createElement('a-text'); text.setAttribute('value', poi.name); text.setAttribute('look-at', '[gps-new-camera]'); text.setAttribute('scale', '50 50 50'); text.setAttribute('position', '0 15 0'); entity.appendChild(text); scene.appendChild(entity); }); }) .catch(error => { console.error('Failed to load POIs:', error); alert('Could not load city data. Check your connection and the backend URL.'); toggleARView(false); }); } // --- MODAL AND UI FUNCTIONS --- function showObjectInfo(poiId) { const poi = poisData.find(p => p.id === poiId); if (!poi) return; objectTitle.textContent = poi.name; objectDescription.textContent = poi.description || "No description available."; objectImage.src = `https://via.placeholder.com/300x200?text=${encodeURIComponent(poi.name)}`; objectModal.classList.remove('hidden'); } function addUserMessage(message) { const chatContainer = aiAssistant.querySelector('.flex-col'); const msg = `

${message}

`; chatContainer.insertAdjacentHTML('beforeend', msg); aiAssistant.scrollTop = aiAssistant.scrollHeight; } function addAIMessage(message) { const chatContainer = aiAssistant.querySelector('.flex-col'); const msg = `
AR Guide

${message}

`; chatContainer.insertAdjacentHTML('beforeend', msg); aiAssistant.scrollTop = aiAssistant.scrollHeight; } function handleSearch() { const searchTerm = userInput.value.trim(); if (!searchTerm) return; addUserMessage(searchTerm); userInput.value = ''; if (poisData.length === 0) { addAIMessage("I'm still loading location data. Please try again in a moment."); return; } const results = poisData.filter(poi => poi.name.toLowerCase().includes(searchTerm.toLowerCase()) || (poi.description && poi.description.toLowerCase().includes(searchTerm.toLowerCase())) ); if (results.length > 0) { let response = `I found ${results.length} result(s):"; addAIMessage(response); } else { addAIMessage(`Sorry, I couldn't find anything matching "${searchTerm}".`); } } // --- EVENT LISTENERS --- arToggle.addEventListener('click', () => toggleARView(!arActive)); document.querySelector('a-scene').addEventListener('click', (event) => { if (event.target.hasAttribute('data-poi-id')) { const poiId = parseInt(event.target.getAttribute('data-poi-id'), 10); showObjectInfo(poiId); } }); closeObjectModal.addEventListener('click', () => objectModal.classList.add('hidden')); sendBtn.addEventListener('click', handleSearch); userInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') handleSearch(); }); // Initial fetch of data so the search bar works immediately fetchPoisAndCreateAREntities(); });