Spaces:
Running
Running
Download script.js from wisdomgreat/simcoe-connect-hub: direct link, hf CLI and curl.
- Browser
- Download file 9.08 kB
-
https://huggingface.co/spaces/wisdomgreat/simcoe-connect-hub/resolve/main/script.js
- Command line
-
hf download hf://spaces/wisdomgreat/simcoe-connect-hub/script.js
-
curl -L -o script.js https://huggingface.co/spaces/wisdomgreat/simcoe-connect-hub/resolve/main/script.js
9.08 kB
| // Main JavaScript for Simcoe Connect Hub | |
| // API Configuration | |
| const API_CONFIG = { | |
| baseURL: '/api', | |
| endpoints: { | |
| weather: '/weather', | |
| alerts: '/alerts', | |
| events: '/events', | |
| businesses: '/businesses', | |
| chat: '/functions/chatbot-rag' | |
| } | |
| }; | |
| // Utility Functions | |
| class Utils { | |
| static formatDate(date) { | |
| return new Intl.DateTimeFormat('en-CA', { | |
| year: 'numeric', | |
| month: 'short', | |
| day: 'numeric', | |
| hour: '2-digit', | |
| minute: '2-digit' | |
| }).format(date); | |
| } | |
| static debounce(func, wait) { | |
| let timeout; | |
| return function executedFunction(...args) { | |
| const later = () => { | |
| clearTimeout(timeout); | |
| func(...args); | |
| }; | |
| clearTimeout(timeout); | |
| timeout = setTimeout(later, wait); | |
| }; | |
| } | |
| static showNotification(message, type = 'info') { | |
| const notification = document.createElement('div'); | |
| notification.className = `fixed top-4 right-4 p-4 rounded-lg shadow-lg z-50 transform transition-transform duration-300 ${ | |
| type === 'error' ? 'bg-red-500 text-white' : | |
| type === 'success' ? 'bg-green-500 text-white' : | |
| 'bg-blue-500 text-white' | |
| }`; | |
| notification.textContent = message; | |
| document.body.appendChild(notification); | |
| setTimeout(() => { | |
| notification.style.transform = 'translateX(100%)'; | |
| setTimeout(() => notification.remove(), 300); | |
| }, 3000); | |
| } | |
| } | |
| // Live Data Management | |
| class LiveDataManager { | |
| static async fetchWeatherData() { | |
| try { | |
| const response = await fetch(`${API_CONFIG.baseURL}${API_CONFIG.endpoints.weather}`); | |
| if (!response.ok) throw new Error('Weather data unavailable'); | |
| return await response.json(); | |
| } catch (error) { | |
| console.error('Failed to fetch weather data:', error); | |
| return null; | |
| } | |
| } | |
| static async fetchWeatherAlerts() { | |
| try { | |
| const response = await fetch(`${API_CONFIG.baseURL}${API_CONFIG.endpoints.alerts}`); | |
| if (!response.ok) throw new Error('Alert data unavailable'); | |
| return await response.json(); | |
| } catch (error) { | |
| console.error('Failed to fetch weather alerts:', error); | |
| return null; | |
| } | |
| } | |
| static async fetchFeaturedEvents() { | |
| try { | |
| const response = await fetch(`${API_CONFIG.baseURL}${API_CONFIG.endpoints.events}?featured=true&limit=3`); | |
| if (!response.ok) throw new Error('Events data unavailable'); | |
| return await response.json(); | |
| } catch (error) { | |
| console.error('Failed to fetch events:', error); | |
| return []; | |
| } | |
| } | |
| static async fetchFeaturedBusinesses() { | |
| try { | |
| const response = await fetch(`${API_CONFIG.baseURL}${API_CONFIG.endpoints.businesses}?featured=true&limit=3`); | |
| if (!response.ok) throw new Error('Businesses data unavailable'); | |
| return await response.json(); | |
| } catch (error) { | |
| console.error('Failed to fetch businesses:', error); | |
| return []; | |
| } | |
| } | |
| } | |
| // UI Controller | |
| class UIController { | |
| static updateWeatherDisplay(weatherData) { | |
| const weatherContainer = document.getElementById('weatherData'); | |
| if (!weatherData) { | |
| weatherContainer.innerHTML = ` | |
| <div class="text-center text-gray-500 py-4"> | |
| <i data-feather="cloud-off" class="w-8 h-8 mx-auto mb-2"></i> | |
| <p>Weather data temporarily unavailable</p> | |
| </div> | |
| `; | |
| return; | |
| } | |
| weatherContainer.innerHTML = ` | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-600">Temperature</span> | |
| <span class="font-semibold text-gray-900">${weatherData.temperature}°C</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-600">Conditions</span> | |
| <span class="font-semibold text-gray-900">${weatherData.conditions}</span> | |
| </div> | |
| <div class="flex justify-between items-center"> | |
| <span class="text-gray-600">Updated</span> | |
| <span class="font-semibold text-gray-900">${Utils.formatDate(new Date(weatherData.updatedAt))}</span> | |
| </div> | |
| `; | |
| feather.replace(); | |
| } | |
| static updateEventsDisplay(events) { | |
| const eventsContainer = document.getElementById('eventsList'); | |
| if (!events || events.length === 0) { | |
| eventsContainer.innerHTML = ` | |
| <div class="text-center text-gray-500 py-4"> | |
| <i data-feather="calendar" class="w-8 h-8 mx-auto mb-2"></i> | |
| <p>No upcoming events</p> | |
| </div> | |
| `; | |
| return; | |
| } | |
| eventsContainer.innerHTML = events.map(event => ` | |
| <div class="border-l-4 border-secondary-500 pl-3 py-1"> | |
| <h4 class="font-semibold text-gray-900 text-sm">${event.title}</h4> | |
| <p class="text-gray-600 text-xs">${Utils.formatDate(new Date(event.date))}</p> | |
| </div> | |
| `).join(''); | |
| } | |
| static updateBusinessesDisplay(businesses) { | |
| const businessesContainer = document.getElementById('businessesList'); | |
| if (!businesses || businesses.length === 0) { | |
| businessesContainer.innerHTML = ` | |
| <div class="text-center text-gray-500 py-4"> | |
| <i data-feather="store" class="w-8 h-8 mx-auto mb-2"></i> | |
| <p>No featured businesses</p> | |
| </div> | |
| `; | |
| return; | |
| } | |
| businessesContainer.innerHTML = businesses.map(business => ` | |
| <div class="flex items-center space-x-3 py-2"> | |
| <div class="w-10 h-10 bg-primary-100 rounded-full flex items-center justify-center"> | |
| <i data-feather="store" class="w-4 h-4 text-primary-600"></i> | |
| </div> | |
| <div> | |
| <h4 class="font-semibold text-gray-900 text-sm">${business.name}</h4> | |
| <p class="text-gray-600 text-xs">${business.category}</p> | |
| </div> | |
| `).join(''); | |
| feather.replace(); | |
| } | |
| static showWeatherAlert(alert) { | |
| if (!alert || !alert.message) return; | |
| const alertBanner = document.getElementById('weatherAlert'); | |
| const alertText = document.getElementById('alertText'); | |
| alertText.textContent = alert.message; | |
| alertBanner.classList.remove('hidden'); | |
| // Add appropriate styling based on alert severity | |
| if (alert.severity === 'high') { | |
| alertBanner.className = alertBanner.className.replace('from-primary-500 to-primary-600', 'from-red-500 to-red-600'); | |
| } | |
| } | |
| } | |
| // Event Handlers | |
| function closeAlert() { | |
| const alertBanner = document.getElementById('weatherAlert'); | |
| alertBanner.classList.add('hidden'); | |
| } | |
| // Search functionality | |
| const searchHandler = Utils.debounce((query) => { | |
| if (query.length > 2) { | |
| window.location.href = `/search?q=${encodeURIComponent(query)}`; | |
| } | |
| }, 500); | |
| document.getElementById('mainSearch')?.addEventListener('input', (e) => { | |
| searchHandler(e.target.value); | |
| }); | |
| // Live Data Loading Functions | |
| async function loadWeatherData() { | |
| const weatherData = await LiveDataManager.fetchWeatherData(); | |
| UIController.updateWeatherDisplay(weatherData); | |
| } | |
| async function checkWeatherAlerts() { | |
| const alerts = await LiveDataManager.fetchWeatherAlerts(); | |
| if (alerts && alerts.length > 0) { | |
| alerts.forEach(alert => UIController.showWeatherAlert(alert)); | |
| } | |
| } | |
| async function loadFeaturedEvents() { | |
| const events = await LiveDataManager.fetchFeaturedEvents(); | |
| UIController.updateEventsDisplay(events); | |
| } | |
| async function loadFeaturedBusinesses() { | |
| const businesses = await LiveDataManager.fetchFeaturedBusinesses(); | |
| UIController.updateBusinessesDisplay(businesses); | |
| } | |
| // Auto-refresh live data every 30 seconds | |
| setInterval(() => { | |
| loadWeatherData(); | |
| loadFeaturedEvents(); | |
| loadFeaturedBusinesses(); | |
| checkWeatherAlerts(); | |
| }, 30000); | |
| // Initialize service worker for offline functionality | |
| if ('serviceWorker' in navigator) { | |
| window.addEventListener('load', () => { | |
| navigator.serviceWorker.register('/sw.js') | |
| .then(registration => { | |
| console.log('SW registered: ', registration); | |
| }) | |
| .catch(registrationError => { | |
| console.log('SW registration failed: ', registrationError); | |
| }); | |
| }); | |
| } | |
| // Error handling | |
| window.addEventListener('error', (event) => { | |
| console.error('Global error:', event.error); | |
| Utils.showNotification('Something went wrong. Please try again.', 'error'); | |
| }); |