import { useQuery } from '@tanstack/react-query'; import ngeohash from 'ngeohash'; import { fetchWeather, fetchAirQuality, fetchWeatherForecast, calculateSkateability, type WeatherData, type AirQualityData, type WeatherForecast, type SkateabilityScore, } from '@/lib/weather'; export interface SpotWeatherData { weather: WeatherData; airQuality?: AirQualityData; forecast?: WeatherForecast; skateability: SkateabilityScore; } /** * Fetch weather data for a single spot by geohash */ export function useSpotWeather(geohash: string | undefined, enabled: boolean = true) { return useQuery({ queryKey: ['spot-weather', geohash], queryFn: async () => { if (!geohash) throw new Error('Geohash is required'); const { latitude, longitude } = ngeohash.decode(geohash); // Fetch weather and air quality in parallel const [weather, airQuality, forecast] = await Promise.all([ fetchWeather(latitude, longitude), fetchAirQuality(latitude, longitude).catch(() => undefined), // Air quality might not be available everywhere fetchWeatherForecast(latitude, longitude).catch(() => undefined), ]); const skateability = calculateSkateability(weather, airQuality); return { weather, airQuality, forecast, skateability, } as SpotWeatherData; }, enabled: enabled && !!geohash, staleTime: 10 * 60 * 1000, // 10 minutes gcTime: 30 * 60 * 1000, // 30 minutes }); } /** * Fetch weather data for multiple spots * Returns a map of geohash -> weather data */ export function useMultipleSpotWeather(geohashes: string[], enabled: boolean = true) { return useQuery({ queryKey: ['multiple-spot-weather', geohashes.sort().join(',')], queryFn: async () => { // Deduplicate geohashes to avoid fetching the same location multiple times const uniqueGeohashes = [...new Set(geohashes)]; // Fetch weather for all spots in parallel const weatherDataPromises = uniqueGeohashes.map(async (geohash) => { try { const { latitude, longitude } = ngeohash.decode(geohash); const [weather, airQuality] = await Promise.all([ fetchWeather(latitude, longitude), fetchAirQuality(latitude, longitude).catch(() => undefined), ]); const skateability = calculateSkateability(weather, airQuality); return { geohash, data: { weather, airQuality, skateability, } as SpotWeatherData, }; } catch (error) { console.error(`Failed to fetch weather for ${geohash}:`, error); return null; } }); const results = await Promise.all(weatherDataPromises); // Convert array to map const weatherMap = new Map(); results.forEach((result) => { if (result) { weatherMap.set(result.geohash, result.data); } }); return weatherMap; }, enabled: enabled && geohashes.length > 0, staleTime: 10 * 60 * 1000, // 10 minutes gcTime: 30 * 60 * 1000, // 30 minutes retry: 2, }); }