/** * Playground Logic (Map Integration) */ const playground = { map: null, currentStyle: 'obsidian', selectedKey: '', init: (keys) => { if (playground.map) return; console.log('πŸ—ΊοΈ Initializing Playground...'); playground.renderKeySelect(keys); playground.bindEvents(); // Watch for section changes to trigger resize window.addEventListener('hashchange', () => { if (window.location.hash === '#playground' && playground.map) { setTimeout(() => playground.map.resize(), 100); } }); if (keys.length > 0) { playground.selectedKey = keys[0].key; playground.loadMap(); } }, renderKeySelect: (keys) => { const select = document.getElementById('pg-key-select'); if (!select) return; select.innerHTML = keys.map(k => ``).join(''); if (keys.length === 0) select.innerHTML = ''; }, bindEvents: () => { const select = document.getElementById('pg-key-select'); if (select) { select.addEventListener('change', (e) => { playground.selectedKey = e.target.value; playground.updateMap(); }); } const searchInput = document.getElementById('pg-search'); if (searchInput) { searchInput.addEventListener('keydown', async (e) => { if (e.key === 'Enter' && searchInput.value) { await playground.handleSearch(searchInput.value); } }); } }, loadMap: async () => { const container = document.getElementById('map'); if (!container || !playground.selectedKey) return; try { // Set RTL Text Plugin if (maplibregl.getRTLTextPluginStatus() === 'unavailable') { console.log('🌐 Loading MapLibre RTL Plugin...'); maplibregl.setRTLTextPlugin( 'js/plugins/mapbox-gl-rtl-text.js', null, true ); } console.log(`πŸ›°οΈ Fetching Map Style for theme: ${playground.currentStyle}...`); const styleUrl = `/api/maps/style.json?api_key=${playground.selectedKey}&theme=${playground.currentStyle}`; const res = await fetch(styleUrl); if (!res.ok) { throw new Error(`Style fetch failed with status: ${res.status}`); } const styleData = await res.json(); console.log('🎨 Style fetched successfully, initializing MapLibre...'); playground.map = new maplibregl.Map({ container: 'map', style: styleData, center: [35.91, 31.95], // Amman, Jordan zoom: 12, attributionControl: false, trackResize: true }); playground.map.addControl(new maplibregl.NavigationControl(), 'top-right'); playground.map.on('load', () => { console.log('βœ… Map engine ready and tiles loading!'); // Wait slightly for container animation to finish setTimeout(() => { playground.map.resize(); const container = document.getElementById('map'); if (container && container.offsetWidth > 0) { console.log('πŸ“ Map container size verified:', container.offsetWidth, 'x', container.offsetHeight); } else { console.warn('⚠️ Map container has 0 width. Potential visibility issue.'); } }, 500); }); playground.map.on('error', (e) => { console.error('❌ MapLibre Error Detail:', e.error || e); if (e.error && e.error.message.includes('Style')) { alert('Map Style Error: Please verify your API Key and Network connection.'); } }); } catch (error) { console.error('Failed to init map', error); } }, updateMap: async () => { if (!playground.map) return; try { const styleUrl = `/api/maps/style.json?api_key=${playground.selectedKey}&theme=${playground.currentStyle}`; const res = await fetch(styleUrl); const styleData = await res.json(); playground.map.setStyle(styleData); } catch (error) { console.error('Failed to update style', error); } }, setStyle: (style) => { playground.currentStyle = style; // Update UI buttons document.getElementById('style-obsidian').className = (style === 'obsidian') ? 'flex-1 py-3 text-xs font-bold rounded-xl bg-blue-600 text-white shadow-lg shadow-blue-500/20' : 'flex-1 py-3 text-xs font-bold rounded-xl bg-slate-900 text-slate-500'; document.getElementById('style-light').className = (style === 'light') ? 'flex-1 py-3 text-xs font-bold rounded-xl bg-blue-600 text-white shadow-lg shadow-blue-500/20' : 'flex-1 py-3 text-xs font-bold rounded-xl bg-slate-900 text-slate-500'; playground.updateMap(); }, handleSearch: async (query) => { try { const res = await fetch(`/api/geocoding/search?q=${encodeURIComponent(query)}`, { headers: { 'x-api-key': playground.selectedKey } }); if (res.ok) { const data = await res.json(); if (data && data.length > 0) { playground.map.flyTo({ center: [data[0].longitude, data[0].latitude], zoom: 14 }); } } } catch (err) { console.error("Search failed", err); } } };