document.addEventListener('DOMContentLoaded', () => { const suggestionForm = document.getElementById('suggestion-form'); const queryInput = document.getElementById('query'); const personaSelect = document.getElementById('persona'); const loadingIndicator = document.getElementById('loading'); const errorMessage = document.getElementById('error-message'); const errorText = document.getElementById('error-text'); const chatContainer = document.getElementById('chat-container'); const luckyButton = document.getElementById('lucky-button'); const funFact = document.getElementById('fun-fact'); let conversation = []; let map; let funFactInterval; const funFacts = [ "Poland is home to the world's largest castle, Malbork Castle.", "The name \"Poland\" (Polska) originates from the Polanie tribe, meaning \"people living in open fields.\"", "Poland has 17 Nobel Prize winners, including four for Peace and five for Literature.", "The Polish alphabet consists of 32 letters.", "Marie Curie, the pioneering scientist, was Polish.", "Poland is the world's biggest exporter of amber.", "The city of Wrocław has a network of over 300 small bronze statues of dwarves (krasnale).", "Poland's Białowieża Forest is one of the last and largest remaining parts of the immense primeval forest that once stretched across the European Plain." ]; suggestionForm.addEventListener('submit', function(e) { e.preventDefault(); const query = queryInput.value.trim(); if (!query) return; const persona = personaSelect.value; const userMessage = { role: 'user', content: query }; conversation.push(userMessage); appendMessage('user', { content: query }); queryInput.value = ''; fetchSuggestions(persona); }); luckyButton.addEventListener('click', function() { const queries = [ "a hidden gem in Warsaw", "the best pierogi in Krakow", "a beautiful beach on the Baltic coast", "a challenging hike in the Tatra Mountains", "a quirky museum in Gdansk" ]; const randomQuery = queries[Math.floor(Math.random() * queries.length)]; queryInput.value = randomQuery; suggestionForm.dispatchEvent(new Event('submit')); }); function showRandomFunFact() { const randomIndex = Math.floor(Math.random() * funFacts.length); funFact.textContent = funFacts[randomIndex]; } function startLoading() { loadingIndicator.style.display = 'block'; showRandomFunFact(); funFactInterval = setInterval(showRandomFunFact, 3000); } function stopLoading() { loadingIndicator.style.display = 'none'; clearInterval(funFactInterval); } function showError(message) { errorText.textContent = message; errorMessage.style.display = 'block'; } function hideError() { errorMessage.style.display = 'none'; } function appendMessage(role, data) { const messageWrapper = document.createElement('div'); messageWrapper.classList.add('message-wrapper', `${role}-wrapper`); const messageBubble = document.createElement('div'); messageBubble.classList.add('message-bubble', `${role}-bubble`); if (role === 'user') { messageBubble.textContent = data.content; } else { if (data.image) { const img = document.createElement('img'); img.src = data.image; img.classList.add('card-img-top'); messageBubble.appendChild(img); } const cardBody = document.createElement('div'); cardBody.classList.add('card-body'); if (data.title) { const title = document.createElement('h5'); title.classList.add('card-title'); title.textContent = data.title; cardBody.appendChild(title); } if (data.description) { const description = document.createElement('p'); description.classList.add('card-text'); description.innerHTML = data.description; // Using innerHTML to render line breaks cardBody.appendChild(description); } if (data.itinerary && data.itinerary.length > 0) { const itinerarySection = document.createElement('div'); itinerarySection.classList.add('itinerary-section'); const itineraryTitle = document.createElement('h6'); itineraryTitle.textContent = 'Itinerary'; itinerarySection.appendChild(itineraryTitle); const itineraryList = document.createElement('ul'); itineraryList.classList.add('list-group'); data.itinerary.forEach(day => { const li = document.createElement('li'); li.classList.add('list-group-item'); li.innerHTML = `Day ${day.day}: ${day.activities.join(', ')}`; itineraryList.appendChild(li); }); itinerarySection.appendChild(itineraryList); cardBody.appendChild(itinerarySection); } if (data.location && data.location.lat && data.location.lng) { const mapId = `map-${Date.now()}`; const mapDiv = document.createElement('div'); mapDiv.id = mapId; mapDiv.style.height = '300px'; mapDiv.classList.add('mt-3'); cardBody.appendChild(mapDiv); // Use a timeout to ensure the div is in the DOM before initializing the map setTimeout(() => { const map = L.map(mapId).setView([data.location.lat, data.location.lng], 13); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); L.marker([data.location.lat, data.location.lng]).addTo(map) .bindPopup(data.title || 'Location') .openPopup(); }, 100); } messageBubble.appendChild(cardBody); const saveButton = document.createElement('button'); saveButton.textContent = 'Save'; saveButton.classList.add('btn', 'btn-sm', 'btn-outline-primary', 'mt-2'); saveButton.addEventListener('click', () => saveSuggestion(data)); cardBody.appendChild(saveButton); } messageWrapper.appendChild(messageBubble); chatContainer.appendChild(messageWrapper); chatContainer.scrollTop = chatContainer.scrollHeight; } function saveSuggestion(suggestionData) { fetch('api/index.php?action=save_suggestion', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(suggestionData) }) .then(response => response.json()) .then(data => { if (data.success) { alert('Suggestion saved!'); } else { showError(data.error || 'Could not save suggestion.'); } }) .catch(error => { console.error('Error:', error); showError('An error occurred while saving the suggestion.'); }); } function fetchSuggestions(persona) { startLoading(); hideError(); fetch('api/index.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ query: conversation[conversation.length - 1].content, persona: persona, conversation: conversation.slice(0, -1) // Send previous conversation }) }) .then(response => { if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } return response.json(); }) .then(data => { stopLoading(); if (data.error) { showError(data.error); // Do not add error to conversation history return; } const assistantMessage = { role: 'assistant', content: data }; conversation.push(assistantMessage); appendMessage('assistant', data); }) .catch(error => { console.error('Error:', error); stopLoading(); showError('An error occurred while fetching the suggestion. Please try again.'); }); } const errorAlert = document.getElementById('error-message'); if (errorAlert) { errorAlert.querySelector('.btn-close').addEventListener('click', function () { hideError(); }); } });